├── .github └── workflows │ ├── build.yaml │ └── publish.yaml ├── .gitignore ├── FUNDING.yml ├── LICENSE ├── README.md ├── codecov.yml ├── docs ├── _config.yml └── index.md ├── fastapi_utilities ├── __init__.py ├── __main__.py ├── cache │ ├── __init__.py │ └── ttl_lru_cache.py ├── cli │ ├── __init__.py │ ├── cli.py │ └── template │ │ ├── .gitignore │ │ ├── README.md │ │ ├── requirements.txt │ │ ├── src │ │ ├── __init__.py │ │ ├── api.py │ │ ├── constants.py │ │ ├── database.py │ │ ├── main.py │ │ └── module1 │ │ │ ├── __init__.py │ │ │ ├── constants.py │ │ │ ├── models.py │ │ │ ├── schemas.py │ │ │ ├── service.py │ │ │ ├── utils.py │ │ │ └── views.py │ │ └── tests │ │ ├── __init__.py │ │ └── test_module1.py ├── py.typed ├── repeat │ ├── __init__.py │ ├── repeat_at.py │ └── repeat_every.py ├── session │ ├── __init__.py │ └── session.py └── timer │ ├── __init__.py │ └── middleware.py ├── poetry.lock ├── pyproject.toml ├── requirements.txt └── tests ├── __init__.py ├── test_repeat_at.py ├── test_repeat_every.py ├── test_session.py └── test_timer_middleware.py /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: 💚Build 2 | 3 | on: 4 | # push: 5 | # branches: 6 | # - master 7 | schedule: 8 | - cron: '30 6 * * *' 9 | pull_request: 10 | branches: 11 | - master 12 | workflow_dispatch: 13 | 14 | 15 | jobs: 16 | build: 17 | runs-on: ubuntu-latest 18 | strategy: 19 | max-parallel: 6 20 | matrix: 21 | python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] 22 | 23 | steps: 24 | - uses: actions/checkout@v4 25 | - name: 🚧 Set up Python ${{ matrix.python-version }} 26 | uses: actions/setup-python@v4 27 | with: 28 | python-version: ${{ matrix.python-version }} 29 | - name: 🚧 Install dependencies 30 | run: | 31 | python -m pip install --upgrade pip 32 | pip install -r requirements.txt 33 | - name: 🧪Run Tests 34 | run: | 35 | python3 -m pytest --cov=fastapi_utilities --cov-report=xml tests/ 36 | - name: ⚗️Submit coverage report 37 | run: | 38 | python3 -m codecov --token=${{ secrets.CODECOV_TOKEN }} 39 | -------------------------------------------------------------------------------- /.github/workflows/publish.yaml: -------------------------------------------------------------------------------- 1 | name: 📦️Upload PyPi Package 2 | 3 | on: 4 | release: 5 | types: [published] 6 | workflow_dispatch: 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | publish: 13 | runs-on: ubuntu-latest 14 | strategy: 15 | max-parallel: 1 16 | matrix: 17 | python-version: ['3.9'] 18 | 19 | steps: 20 | - uses: actions/checkout@v4 21 | - name: Set up Python ${{ matrix.python-version }} 22 | uses: actions/setup-python@v4 23 | with: 24 | python-version: ${{ matrix.python-version }} 25 | - name: Install dependencies 26 | run: | 27 | python -m pip install --upgrade pip 28 | pip install -r requirements.txt 29 | - name: Run Tests 30 | run: | 31 | python3 -m pytest tests/ 32 | - name: Install poetry 33 | run: | 34 | curl -sSL https://install.python-poetry.org | python3 - 35 | - name: Build distribution 36 | run: | 37 | poetry build 38 | - name: Publish distribution to PyPI 39 | uses: pypa/gh-action-pypi-publish@master 40 | with: 41 | user: __token__ 42 | password: ${{ secrets.PYPI_API_TOKEN }} 43 | -------------------------------------------------------------------------------- /.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 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | .venv 125 | env/ 126 | venv/ 127 | ENV/ 128 | env.bak/ 129 | venv.bak/ 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | #.idea/ 161 | -------------------------------------------------------------------------------- /FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: 2 | funding: 3 | - type: "individual" 4 | url: "https://github.com/sponsors/priyanshu-panwar" 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Priyanshu Panwar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 🎨⚡️🔥 Reusable Utilities for FastAPI 3 |

4 |

5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | Package version 15 | 16 | PyPI - Python Version 17 | PyPI - Python Version 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |

29 | 30 | --- 31 | **Features**: 32 | - Repeat At / Every for scheduling cron jobs 33 | - TTL LRU Cache 34 | - Timing Middleware that logs you the time taken by a request 35 | - Session Middleware 36 | - CLI tool to generate skeleton 37 | 38 | 39 | --- 40 | 41 | **Source Code**: https://github.com/priyanshu-panwar/fastapi-utilities 42 | **Youtube Link**: [Click Here](https://youtu.be/ZIggeTU8JhQ?si=SO1B0Is0RdXDkbCa) 43 | 44 | _Inspired From_: dmontagu/fastapi-utils 45 | 46 | --- 47 | 48 | ## [✨Update✨] How to use with Latest FastAPI version 49 | 50 | With the latest FastAPI version, `on_event` lifespan functions are depreceated. Here is the official [doc](https://fastapi.tiangolo.com/advanced/events/#async-context-manager). 51 | We need to make use of `asynccontextmanager` with the latest fastapi. 52 | 53 | Here is an example how to use lifespan (Repeated Tasks) functions with latest fastapi: 54 | 55 | ``` 56 | from fastapi import FastAPI 57 | from contextlib import asynccontextmanager 58 | from fastapi_utilities import repeat_every, repeat_at 59 | 60 | @asynccontextmanager 61 | async def lifespan(app: FastAPI): 62 | # --- startup --- 63 | await test() 64 | test2() 65 | yield 66 | # --- shutdown --- 67 | 68 | app = FastAPI(lifespan=lifespan) 69 | 70 | # Repeat Every Example 71 | @repeat_every(seconds=2) 72 | async def test(): 73 | print("test") 74 | 75 | # Repeat At Example 76 | @repeat_at(cron="* * * * *") 77 | def test2(): 78 | print("test2") 79 | ``` 80 | 81 | Only difference is to call our tasks from lifespan function instead of using `on_event` function. 82 | 83 | --- 84 | 85 | ## [🔥New🔥] TTL LRU CACHE 86 | 87 | We have introduced `ttl_lru_cache` now in our library. 88 | 89 | ### How to use 90 | 91 | ``` 92 | from fastapi_utilities import ttl_lru_cache 93 | 94 | @ttl_lru_cache(ttl=2, max_size=128) 95 | def sum(a: int, b: int) -> int: 96 | return a + b 97 | 98 | sum(1, 3) 99 | sum(1, 3) 100 | ``` 101 | 102 | --- 103 | 104 | ## [🔥New🔥] FastAPI CLI Tool 105 | 106 | With our CLI Tool you can get a skeleton project built to get you started with the code. 107 | 108 | ### How to use 109 | 110 | - Using `poetry`: `poetry run cli init` 111 | - Using `pip`: `python3 -m cli init` 112 | 113 | --- 114 | 115 | ## Features 116 | 117 | This package includes a number of utilities to help reduce boilerplate and reuse common functionality across projects: 118 | 119 | - **🕒Repeated Tasks**: Easily trigger periodic tasks on server startup using **repeat_every**. 120 | 121 | ``` 122 | 123 | from fastapi_utilities import repeat_every 124 | 125 | @router.on_event('startup') 126 | @repeat_every(seconds=3) 127 | async def print_hello(): 128 | 129 | print("hello") 130 | ``` 131 | 132 | - **👷Cron Jobs**: Easily trigger cron jobs on server startup using **repeat_at** by providing a cron expression. 133 | 134 | ``` 135 | 136 | from fastapi_utilities import repeat_at 137 | 138 | @router.on_event("startup") 139 | @repeat_at(cron="*/2 * * * *") #every 2nd minute 140 | async def hey(): 141 | print("hey") 142 | 143 | ``` 144 | 145 | - **🕒Timer Middleware**: Add a middleware to the FastAPI app that logs the time taken to process a request. Optionally, also logs the average response time.The average response time is reset after every (reset_after)100,000 requests. 146 | 147 | ``` 148 | 149 | import asyncio 150 | from fastapi import FastAPI, Request 151 | from fastapi_utilities import add_timer_middleware 152 | 153 | app = FastAPI() 154 | add_timer_middleware(app, show_avg=True) 155 | 156 | 157 | @app.get("/") 158 | def read_root(): 159 | return {"message": "Hello, World!"} 160 | 161 | ``` 162 | 163 | Response Logs: 164 | 165 | ``` 166 | INFO: (fastapi-utilities) "GET - /" :: Time Taken :: 0.97 ms 167 | INFO: :: Average Response Time :: 0.97 ms 168 | ``` 169 | 170 | - **Cached Sessions**: Now use cached sessions along with context manager instead of `get_db`. 171 | 172 | ``` 173 | from fastapi import FastAPI 174 | from .db import Base, engine 175 | from fastapi_utilities import FastAPISessionMaker, repeat_every 176 | from .models import User 177 | import random 178 | 179 | app = FastAPI() 180 | Base.metadata.create_all(bind=engine) 181 | 182 | session_maker = FastAPISessionMaker("sqlite:///db.sqlite3") 183 | 184 | 185 | @app.on_event("startup") 186 | @repeat_every(seconds=5, raise_exceptions=True) 187 | async def startup(): 188 | print("Starting up...") 189 | with session_maker.context_session() as session: 190 | x = User(id=random.randint(0, 10000)) 191 | session.add(x) 192 | print("Startup complete!") 193 | 194 | ``` 195 | 196 | --- 197 | 198 | ## Requirements 199 | 200 | This package is intended for use with any recent version of FastAPI and Python 3.7+. 201 | 202 | ## Installation 203 | 204 | ```bash 205 | pip install fastapi-utilities 206 | ``` 207 | 208 | ## License 209 | 210 | This project is licensed under the terms of the MIT license. 211 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | project: 4 | default: 5 | target: auto 6 | threshold: 100% -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | title: fastapi-utilities 2 | description: 🎨⚡️🔥 Reusable Utilities for FastAPI 3 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 |

2 | 🎨⚡️🔥 Reusable Utilities for FastAPI 3 |

4 |

5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | Package version 15 | 16 | PyPI - Python Version 17 | PyPI - Python Version 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |

29 | 30 | --- 31 | 32 | **Source Code**: https://github.com/priyanshu-panwar/fastapi-utilities 33 | **Youtube Link**: [Click Here](https://youtu.be/ZIggeTU8JhQ?si=SO1B0Is0RdXDkbCa) 34 | 35 | _Inspired From_: dmontagu/fastapi-utils 36 | 37 | --- 38 | 39 | ## [✨Update✨] How to use with Latest FastAPI version 40 | 41 | With the latest FastAPI version, `on_event` lifespan functions are depreceated. Here is the official [doc](https://fastapi.tiangolo.com/advanced/events/#async-context-manager). 42 | We need to make use of `asynccontextmanager` with the latest fastapi. 43 | 44 | Here is an example how to use lifespan (Repeated Tasks) functions with latest fastapi: 45 | 46 | ``` 47 | from fastapi import FastAPI 48 | from contextlib import asynccontextmanager 49 | from fastapi_utilities.repeat import repeat_every, repeat_at 50 | 51 | @asynccontextmanager 52 | async def lifespan(app: FastAPI): 53 | # --- startup --- 54 | await test() 55 | test2() 56 | yield 57 | # --- shutdown --- 58 | 59 | app = FastAPI(lifespan=lifespan) 60 | 61 | # Repeat Every Example 62 | @repeat_every(seconds=2) 63 | async def test(): 64 | print("test") 65 | 66 | # Repeat At Example 67 | @repeat_at(cron="* * * * *") 68 | def test2(): 69 | print("test2") 70 | ``` 71 | 72 | Only difference is to call our tasks from lifespan function instead of using `on_event` function. 73 | 74 | --- 75 | 76 | ## [🔥New🔥] TTL LRU CACHE 77 | 78 | We have introduced `ttl_lru_cache` now in our library. 79 | 80 | ### How to use 81 | 82 | ``` 83 | from fastapi_utilities import ttl_lru_cache 84 | 85 | @ttl_lru_cache(ttl=2, max_size=128) 86 | def sum(a: int, b: int) -> int: 87 | return a + b 88 | 89 | sum(1, 3) 90 | sum(1, 3) 91 | ``` 92 | 93 | --- 94 | 95 | ## [🔥New🔥] FastAPI CLI Tool 96 | 97 | With our CLI Tool you can get a skeleton project built to get you started with the code. 98 | 99 | ### How to use 100 | 101 | - Using `poetry`: `poetry run cli init` 102 | - Using `pip`: `python3 -m cli init` 103 | 104 | --- 105 | 106 | ## Features 107 | 108 | This package includes a number of utilities to help reduce boilerplate and reuse common functionality across projects: 109 | 110 | - **🕒Repeated Tasks**: Easily trigger periodic tasks on server startup using **repeat_every**. 111 | 112 | ``` 113 | 114 | from fastapi_utilities import repeat_every 115 | 116 | @router.on_event('startup') 117 | @repeat_every(seconds=3) 118 | async def print_hello(): 119 | 120 | print("hello") 121 | ``` 122 | 123 | - **👷Cron Jobs**: Easily trigger cron jobs on server startup using **repeat_at** by providing a cron expression. 124 | 125 | ``` 126 | 127 | from fastapi_utilities import repeat_at 128 | 129 | @router.on_event("startup") 130 | @repeat_at(cron="*/2 * * * *") #every 2nd minute 131 | async def hey(): 132 | print("hey") 133 | 134 | ``` 135 | 136 | - **🕒Timer Middleware**: Add a middleware to the FastAPI app that logs the time taken to process a request. Optionally, also logs the average response time.The average response time is reset after every (reset_after)100,000 requests. 137 | 138 | ``` 139 | 140 | import asyncio 141 | from fastapi import FastAPI, Request 142 | from fastapi_utilities import add_timer_middleware 143 | 144 | app = FastAPI() 145 | add_timer_middleware(app, show_avg=True) 146 | 147 | 148 | @app.get("/") 149 | def read_root(): 150 | return {"message": "Hello, World!"} 151 | 152 | ``` 153 | 154 | Response Logs: 155 | 156 | ``` 157 | INFO: (fastapi-utilities) "GET - /" :: Time Taken :: 0.97 ms 158 | INFO: :: Average Response Time :: 0.97 ms 159 | ``` 160 | 161 | - **Cached Sessions**: Now use cached sessions along with context manager instead of `get_db`. 162 | 163 | ``` 164 | from fastapi import FastAPI 165 | from .db import Base, engine 166 | from fastapi_utilities import FastAPISessionMaker, repeat_every 167 | from .models import User 168 | import random 169 | 170 | app = FastAPI() 171 | Base.metadata.create_all(bind=engine) 172 | 173 | session_maker = FastAPISessionMaker("sqlite:///db.sqlite3") 174 | 175 | 176 | @app.on_event("startup") 177 | @repeat_every(seconds=5, raise_exceptions=True) 178 | async def startup(): 179 | print("Starting up...") 180 | with session_maker.context_session() as session: 181 | x = User(id=random.randint(0, 10000)) 182 | session.add(x) 183 | print("Startup complete!") 184 | 185 | ``` 186 | 187 | --- 188 | 189 | ## Requirements 190 | 191 | This package is intended for use with any recent version of FastAPI and Python 3.7+. 192 | 193 | ## Installation 194 | 195 | ```bash 196 | pip install fastapi-utilities 197 | ``` 198 | 199 | ## License 200 | 201 | This project is licensed under the terms of the MIT license. 202 | -------------------------------------------------------------------------------- /fastapi_utilities/__init__.py: -------------------------------------------------------------------------------- 1 | from .repeat.repeat_every import repeat_every 2 | from .repeat.repeat_at import repeat_at 3 | 4 | from .timer import add_timer_middleware 5 | 6 | from .session import FastAPISessionMaker 7 | 8 | from .cache import ttl_lru_cache 9 | -------------------------------------------------------------------------------- /fastapi_utilities/__main__.py: -------------------------------------------------------------------------------- 1 | from .cli.cli import main 2 | 3 | if __name__ == "__main__": 4 | main() 5 | -------------------------------------------------------------------------------- /fastapi_utilities/cache/__init__.py: -------------------------------------------------------------------------------- 1 | from .ttl_lru_cache import ttl_lru_cache 2 | -------------------------------------------------------------------------------- /fastapi_utilities/cache/ttl_lru_cache.py: -------------------------------------------------------------------------------- 1 | from functools import lru_cache, wraps 2 | from typing import Callable 3 | import time 4 | 5 | 6 | def ttl_lru_cache(ttl: int, max_size: int = 128) -> Callable: 7 | """ 8 | This function is a decorator that wraps the lru_cache decorator. 9 | """ 10 | 11 | def decorator(func) -> Callable: 12 | @lru_cache(maxsize=max_size) 13 | def _new(*args, __time_salt, **kwargs): 14 | return func(*args, **kwargs) 15 | 16 | @wraps(func) 17 | def wrapper(*args, **kwargs): 18 | if ttl: 19 | return _new(*args, __time_salt=int(time.time() / ttl), **kwargs) 20 | return func(*args, **kwargs) 21 | 22 | wrapper.cache_clear = _new.cache_clear 23 | return wrapper 24 | 25 | return decorator 26 | -------------------------------------------------------------------------------- /fastapi_utilities/cli/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priyanshu-panwar/fastapi-utilities/733a60981f27515464f2d5c2d8ec0c6885dda0a2/fastapi_utilities/cli/__init__.py -------------------------------------------------------------------------------- /fastapi_utilities/cli/cli.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os 3 | import click_spinner 4 | import time 5 | import shutil 6 | 7 | TEMPLATE_FOLDER = os.path.join(os.path.dirname(__file__), "template") 8 | 9 | 10 | def copy_template_files(destination_folder): 11 | """ 12 | Copy template files to the destination folder. 13 | """ 14 | for root, dirs, files in os.walk(TEMPLATE_FOLDER): 15 | for file in files: 16 | src_file = os.path.join(root, file) 17 | dest_file = os.path.join( 18 | destination_folder, os.path.relpath(src_file, TEMPLATE_FOLDER) 19 | ) 20 | os.makedirs(os.path.dirname(dest_file), exist_ok=True) 21 | shutil.copy(src_file, dest_file) 22 | 23 | 24 | def init_project(project_name: str): 25 | """ 26 | Initialize a new FastAPI project 27 | """ 28 | # Create project folder 29 | project_folder = os.path.join(os.getcwd(), project_name) 30 | os.makedirs(project_folder, exist_ok=True) 31 | 32 | copy_template_files(project_folder) 33 | 34 | 35 | def init(args): 36 | """ 37 | Initialize FastAPI Utilities CLI 38 | """ 39 | print("Welcome to FastAPI Utilities CLI Tool") 40 | 41 | project_name = input("Enter the project name: ") 42 | 43 | with click_spinner.spinner(f"Creating project '{project_name}'..."): 44 | init_project(project_name) 45 | time.sleep(1) 46 | 47 | print("Project created successfully") 48 | 49 | 50 | def main(): 51 | """ 52 | Main function for FastAPI Utilities CLI Tool 53 | """ 54 | parser = argparse.ArgumentParser(description="FastAPI Utilities CLI Tool") 55 | subparsers = parser.add_subparsers(title="subcommands", dest="subcommand") 56 | 57 | # Create 'init' subcommand 58 | parser_init = subparsers.add_parser("init", help="Initialize FastAPI Utilities CLI") 59 | parser_init.set_defaults(func=init) 60 | 61 | try: 62 | args = parser.parse_args() 63 | args.func(args) 64 | except AttributeError: 65 | parser.print_help() 66 | 67 | 68 | if __name__ == "__main__": 69 | main() 70 | -------------------------------------------------------------------------------- /fastapi_utilities/cli/template/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc -------------------------------------------------------------------------------- /fastapi_utilities/cli/template/README.md: -------------------------------------------------------------------------------- 1 | # My Project 2 | 3 | ## How to start project 4 | - `pip install -r requirements.txt` 5 | - `uvicorn src.main:app --reload` 6 | - Project started on `8000` port. 7 | 8 | 9 | `Built with FastAPI Utilities CLI Tool` -------------------------------------------------------------------------------- /fastapi_utilities/cli/template/requirements.txt: -------------------------------------------------------------------------------- 1 | # add requirements here 2 | # pip install -r requirements.txt 3 | 4 | fastapi 5 | uvicorn 6 | sqlmodel -------------------------------------------------------------------------------- /fastapi_utilities/cli/template/src/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priyanshu-panwar/fastapi-utilities/733a60981f27515464f2d5c2d8ec0c6885dda0a2/fastapi_utilities/cli/template/src/__init__.py -------------------------------------------------------------------------------- /fastapi_utilities/cli/template/src/api.py: -------------------------------------------------------------------------------- 1 | # Define all the router here. 2 | 3 | from fastapi import APIRouter 4 | from .module1.views import router as module1_router 5 | 6 | router = APIRouter() 7 | router.include_router(module1_router) 8 | -------------------------------------------------------------------------------- /fastapi_utilities/cli/template/src/constants.py: -------------------------------------------------------------------------------- 1 | # Define global constants here 2 | 3 | DATABASE_URL = "" 4 | -------------------------------------------------------------------------------- /fastapi_utilities/cli/template/src/database.py: -------------------------------------------------------------------------------- 1 | # Define database connection here 2 | 3 | from sqlalchemy import create_engine 4 | from sqlalchemy.orm import sessionmaker 5 | from src import constants 6 | 7 | engine = create_engine( 8 | constants.DATABASE_URL, connect_args={"check_same_thread": False} 9 | ) 10 | SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) 11 | 12 | 13 | def get_db(): 14 | db = SessionLocal() 15 | try: 16 | yield db 17 | finally: 18 | db.close() 19 | -------------------------------------------------------------------------------- /fastapi_utilities/cli/template/src/main.py: -------------------------------------------------------------------------------- 1 | # Sample main file 2 | 3 | from fastapi import FastAPI 4 | from .api import router 5 | 6 | app = FastAPI("My App") 7 | app.include_router(router) 8 | -------------------------------------------------------------------------------- /fastapi_utilities/cli/template/src/module1/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priyanshu-panwar/fastapi-utilities/733a60981f27515464f2d5c2d8ec0c6885dda0a2/fastapi_utilities/cli/template/src/module1/__init__.py -------------------------------------------------------------------------------- /fastapi_utilities/cli/template/src/module1/constants.py: -------------------------------------------------------------------------------- 1 | # Define your module's constants here 2 | 3 | # MY_CONSTANT = "my_constant" 4 | -------------------------------------------------------------------------------- /fastapi_utilities/cli/template/src/module1/models.py: -------------------------------------------------------------------------------- 1 | # Define your module's models here 2 | 3 | from pydantic import BaseModel 4 | 5 | 6 | class MyModel(BaseModel): 7 | pass 8 | -------------------------------------------------------------------------------- /fastapi_utilities/cli/template/src/module1/schemas.py: -------------------------------------------------------------------------------- 1 | # Define your module's schemas here 2 | 3 | from pydantic import BaseModel 4 | 5 | 6 | class MySchema(BaseModel): 7 | pass 8 | -------------------------------------------------------------------------------- /fastapi_utilities/cli/template/src/module1/service.py: -------------------------------------------------------------------------------- 1 | # Define your module's crud operations here 2 | 3 | from typing import List 4 | from fastapi import Depends 5 | from sqlalchemy.orm import Session 6 | from . import models, schemas 7 | from src import utils 8 | 9 | 10 | async def get_all(db: Session = Depends(utils.get_db)) -> List[models.MyModel]: 11 | pass 12 | -------------------------------------------------------------------------------- /fastapi_utilities/cli/template/src/module1/utils.py: -------------------------------------------------------------------------------- 1 | # Define your module's utils here 2 | -------------------------------------------------------------------------------- /fastapi_utilities/cli/template/src/module1/views.py: -------------------------------------------------------------------------------- 1 | # Define your module's routes here 2 | 3 | from fastapi import APIRouter 4 | 5 | router = APIRouter(prefix="/module1", tags=["module1"]) 6 | from . import utils, services, models 7 | 8 | 9 | @router.get("/") 10 | async def root(): 11 | return {"message": "Hello World"} 12 | -------------------------------------------------------------------------------- /fastapi_utilities/cli/template/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priyanshu-panwar/fastapi-utilities/733a60981f27515464f2d5c2d8ec0c6885dda0a2/fastapi_utilities/cli/template/tests/__init__.py -------------------------------------------------------------------------------- /fastapi_utilities/cli/template/tests/test_module1.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priyanshu-panwar/fastapi-utilities/733a60981f27515464f2d5c2d8ec0c6885dda0a2/fastapi_utilities/cli/template/tests/test_module1.py -------------------------------------------------------------------------------- /fastapi_utilities/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priyanshu-panwar/fastapi-utilities/733a60981f27515464f2d5c2d8ec0c6885dda0a2/fastapi_utilities/py.typed -------------------------------------------------------------------------------- /fastapi_utilities/repeat/__init__.py: -------------------------------------------------------------------------------- 1 | from .repeat_at import repeat_at 2 | from .repeat_every import repeat_every -------------------------------------------------------------------------------- /fastapi_utilities/repeat/repeat_at.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import logging 3 | import typing 4 | 5 | from datetime import datetime 6 | from functools import wraps 7 | from asyncio import ensure_future 8 | from starlette.concurrency import run_in_threadpool 9 | from croniter import croniter 10 | 11 | _FuncType = typing.TypeVar("_FuncType", bound=typing.Callable) 12 | 13 | 14 | def get_delta(cron: str) -> float: 15 | """ 16 | Returns the time delta between now and the next cron execution time. 17 | """ 18 | now = datetime.now() 19 | cron = croniter(cron, now) 20 | return (cron.get_next(datetime) - now).total_seconds() 21 | 22 | def repeat_at( 23 | *, 24 | cron: str, 25 | logger: logging.Logger = None, 26 | raise_exceptions: bool = False, 27 | max_repetitions: int = None, 28 | ) -> typing.Callable[[_FuncType], _FuncType]: 29 | """ 30 | Decorator to schedule a function's execution based on a cron expression. 31 | 32 | Parameters: 33 | ----------- 34 | cron: str 35 | Cron-style string for periodic execution, e.g., '0 0 * * *' for every midnight. 36 | logger: logging.Logger (default None) 37 | Logger object to log exceptions. 38 | raise_exceptions: bool (default False) 39 | Whether to raise exceptions or log them. 40 | max_repetitions: int (default None) 41 | Maximum number of times to repeat the function. If None, repeats indefinitely. 42 | """ 43 | 44 | def decorator(func: _FuncType) -> _FuncType: 45 | is_coroutine = asyncio.iscoroutinefunction(func) 46 | 47 | @wraps(func) 48 | async def async_wrapper(*args, **kwargs): 49 | repetitions = 0 50 | if not croniter.is_valid(cron): 51 | raise ValueError(f"Invalid cron expression: '{cron}'") 52 | 53 | while max_repetitions is None or repetitions < max_repetitions: 54 | try: 55 | sleep_time = get_delta(cron) 56 | await asyncio.sleep(sleep_time) 57 | await func(*args, **kwargs) 58 | except Exception as e: 59 | if logger: 60 | logger.exception(e) 61 | if raise_exceptions: 62 | raise e 63 | repetitions += 1 64 | 65 | @wraps(func) 66 | def sync_wrapper(*args, **kwargs): 67 | repetitions = 0 68 | if not croniter.is_valid(cron): 69 | raise ValueError(f"Invalid cron expression: '{cron}'") 70 | 71 | async def loop(): 72 | nonlocal repetitions 73 | while max_repetitions is None or repetitions < max_repetitions: 74 | try: 75 | sleep_time = get_delta(cron) 76 | await asyncio.sleep(sleep_time) 77 | await run_in_threadpool(func, *args, **kwargs) 78 | except Exception as e: 79 | if logger: 80 | logger.exception(e) 81 | if raise_exceptions: 82 | raise e 83 | repetitions += 1 84 | 85 | ensure_future(loop()) 86 | 87 | # Return the appropriate wrapper based on the function type 88 | return async_wrapper if is_coroutine else sync_wrapper 89 | 90 | return decorator 91 | -------------------------------------------------------------------------------- /fastapi_utilities/repeat/repeat_every.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import logging 3 | import typing 4 | 5 | from functools import wraps 6 | from asyncio import ensure_future 7 | from starlette.concurrency import run_in_threadpool 8 | 9 | 10 | _FuncType = typing.TypeVar("_FuncType", bound=typing.Callable) 11 | 12 | 13 | def repeat_every( 14 | *, 15 | seconds: float, 16 | wait_first: bool = False, 17 | logger: logging.Logger = None, 18 | raise_exceptions: bool = False, 19 | max_repetitions: int = None, 20 | ) -> typing.Callable[[_FuncType], _FuncType]: 21 | """ 22 | This function returns a decorator that schedules a function to execute periodically after every `seconds` seconds. 23 | 24 | :: Params :: 25 | ------------ 26 | seconds: float 27 | The number of seconds to wait before executing the function again. 28 | wait_first: bool (default False) 29 | Whether to wait `seconds` seconds before executing the function for the first time. 30 | logger: logging.Logger (default None) 31 | The logger to use for logging exceptions. 32 | raise_exceptions: bool (default False) 33 | Whether to raise exceptions instead of logging them. 34 | max_repetitions: int (default None) 35 | The maximum number of times to repeat the function. If None, the function will repeat indefinitely. 36 | """ 37 | 38 | def decorator(func: _FuncType) -> _FuncType: 39 | is_coroutine = asyncio.iscoroutinefunction(func) 40 | 41 | @wraps(func) 42 | async def wrapper(*args, **kwargs): 43 | repetitions = 0 44 | 45 | async def loop(*args, **kwargs): 46 | nonlocal repetitions 47 | if wait_first: 48 | await asyncio.sleep(seconds) 49 | while max_repetitions is None or repetitions < max_repetitions: 50 | try: 51 | if is_coroutine: 52 | await func(*args, **kwargs) 53 | else: 54 | await run_in_threadpool(func, *args, **kwargs) 55 | except Exception as e: 56 | if logger is not None: 57 | logger.exception(e) 58 | if raise_exceptions: 59 | raise e 60 | repetitions += 1 61 | await asyncio.sleep(seconds) 62 | 63 | ensure_future(loop(*args, **kwargs)) 64 | 65 | return wrapper 66 | 67 | return decorator 68 | -------------------------------------------------------------------------------- /fastapi_utilities/session/__init__.py: -------------------------------------------------------------------------------- 1 | from .session import FastAPISessionMaker 2 | -------------------------------------------------------------------------------- /fastapi_utilities/session/session.py: -------------------------------------------------------------------------------- 1 | from contextlib import contextmanager 2 | from sqlalchemy import create_engine 3 | from sqlalchemy.engine import Engine 4 | from sqlalchemy.orm import Session, sessionmaker 5 | 6 | 7 | class FastAPISessionMaker: 8 | """ 9 | This will allow us to create a cached session maker that can be used as context manager. 10 | """ 11 | 12 | def __init__(self, db_url: str): 13 | """ 14 | `db_url` should be any sqlalchemy-compatible database URI. 15 | """ 16 | self.db_url = db_url 17 | self._cached_engine: Engine = None 18 | self._cached_session_maker: Session = None 19 | 20 | def _get_db(self): 21 | """ 22 | This will return a cached db connection Session. 23 | """ 24 | if self._cached_engine is None: 25 | self._cached_engine = create_engine(self.db_url) 26 | if self._cached_session_maker is None: 27 | self._cached_session_maker = sessionmaker( 28 | autocommit=False, autoflush=False, bind=self._cached_engine 29 | ) 30 | db = self._cached_session_maker() 31 | try: 32 | yield db 33 | db.commit() 34 | except Exception as e: 35 | db.rollback() 36 | raise e 37 | finally: 38 | db.close() 39 | 40 | @contextmanager 41 | def context_session(self): 42 | """ 43 | A context manager that works for `get_db` dependency injection. 44 | 45 | Usage: 46 | session_maker = FastAPISessionMaker(database_uri) 47 | with session_maker.context_session() as session: 48 | session.query(...) 49 | """ 50 | yield from self._get_db() 51 | 52 | def reset_session(self): 53 | """ 54 | This will reset the sessionmaker and engine. 55 | """ 56 | self._cached_session_maker = None 57 | self._cached_engine = None 58 | -------------------------------------------------------------------------------- /fastapi_utilities/timer/__init__.py: -------------------------------------------------------------------------------- 1 | from .middleware import add_timer_middleware 2 | -------------------------------------------------------------------------------- /fastapi_utilities/timer/middleware.py: -------------------------------------------------------------------------------- 1 | """ 2 | Based on https://github.com/dmontagu/fastapi-utils/blob/master/fastapi_utils/timing.py 3 | """ 4 | 5 | import time 6 | from typing import Callable 7 | from fastapi import FastAPI, Request 8 | import logging 9 | 10 | TIMER_PREFIX = "(fastapi-utilities)" 11 | 12 | 13 | def add_timer_middleware( 14 | app: FastAPI, 15 | show_avg: bool = False, 16 | reset_after: int = 100000, 17 | ) -> None: 18 | """ 19 | Add a middleware to the FastAPI app that logs the time taken to process a request. 20 | Optionally, also logs the average response time. 21 | The average response time is reset after every (reset_after)100,000 requests. 22 | 23 | ::Params:: 24 | ---------- 25 | app: FastAPI 26 | The FastAPI app to add the middleware to. 27 | show_avg: bool (default False) 28 | Whether to show the average response time in the logs. 29 | reset_after: int (default 100000) 30 | The number of requests after which to reset the average response time. 31 | """ 32 | 33 | logger = logging.getLogger("uvicorn") 34 | 35 | request_counter = 0 36 | total_response_time = 0.0 37 | 38 | @app.middleware("http") 39 | async def timer_middleware(request: Request, call_next): 40 | nonlocal request_counter, total_response_time 41 | 42 | start_time = time.time() 43 | response = await call_next(request) 44 | process_time = (time.time() - start_time) * 1000 45 | logger.info( 46 | f'{TIMER_PREFIX} "{request.method} - {request.url.path}" :: Time Taken :: {process_time:.2f} ms' 47 | ) 48 | 49 | if show_avg: 50 | request_counter += 1 51 | total_response_time += process_time 52 | average_response_time = ( 53 | total_response_time / request_counter if request_counter > 0 else 0 54 | ) 55 | logger.info(f":: Average Response Time :: {average_response_time:.2f} ms") 56 | 57 | if request_counter % reset_after == 0: 58 | request_counter = 0 59 | total_response_time = 0.0 60 | 61 | return response 62 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "annotated-types" 5 | version = "0.5.0" 6 | description = "Reusable constraint types to use with typing.Annotated" 7 | optional = false 8 | python-versions = ">=3.7" 9 | files = [ 10 | {file = "annotated_types-0.5.0-py3-none-any.whl", hash = "sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd"}, 11 | {file = "annotated_types-0.5.0.tar.gz", hash = "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802"}, 12 | ] 13 | 14 | [package.dependencies] 15 | typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} 16 | 17 | [[package]] 18 | name = "anyio" 19 | version = "3.7.1" 20 | description = "High level compatibility layer for multiple asynchronous event loop implementations" 21 | optional = false 22 | python-versions = ">=3.7" 23 | files = [ 24 | {file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"}, 25 | {file = "anyio-3.7.1.tar.gz", hash = "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780"}, 26 | ] 27 | 28 | [package.dependencies] 29 | exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} 30 | idna = ">=2.8" 31 | sniffio = ">=1.1" 32 | typing-extensions = {version = "*", markers = "python_version < \"3.8\""} 33 | 34 | [package.extras] 35 | doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"] 36 | test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] 37 | trio = ["trio (<0.22)"] 38 | 39 | [[package]] 40 | name = "certifi" 41 | version = "2024.7.4" 42 | description = "Python package for providing Mozilla's CA Bundle." 43 | optional = false 44 | python-versions = ">=3.6" 45 | files = [ 46 | {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, 47 | {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, 48 | ] 49 | 50 | [[package]] 51 | name = "charset-normalizer" 52 | version = "3.3.0" 53 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 54 | optional = false 55 | python-versions = ">=3.7.0" 56 | files = [ 57 | {file = "charset-normalizer-3.3.0.tar.gz", hash = "sha256:63563193aec44bce707e0c5ca64ff69fa72ed7cf34ce6e11d5127555756fd2f6"}, 58 | {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:effe5406c9bd748a871dbcaf3ac69167c38d72db8c9baf3ff954c344f31c4cbe"}, 59 | {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4162918ef3098851fcd8a628bf9b6a98d10c380725df9e04caf5ca6dd48c847a"}, 60 | {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0570d21da019941634a531444364f2482e8db0b3425fcd5ac0c36565a64142c8"}, 61 | {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5707a746c6083a3a74b46b3a631d78d129edab06195a92a8ece755aac25a3f3d"}, 62 | {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:278c296c6f96fa686d74eb449ea1697f3c03dc28b75f873b65b5201806346a69"}, 63 | {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a4b71f4d1765639372a3b32d2638197f5cd5221b19531f9245fcc9ee62d38f56"}, 64 | {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5969baeaea61c97efa706b9b107dcba02784b1601c74ac84f2a532ea079403e"}, 65 | {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3f93dab657839dfa61025056606600a11d0b696d79386f974e459a3fbc568ec"}, 66 | {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:db756e48f9c5c607b5e33dd36b1d5872d0422e960145b08ab0ec7fd420e9d649"}, 67 | {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:232ac332403e37e4a03d209a3f92ed9071f7d3dbda70e2a5e9cff1c4ba9f0678"}, 68 | {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e5c1502d4ace69a179305abb3f0bb6141cbe4714bc9b31d427329a95acfc8bdd"}, 69 | {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:2502dd2a736c879c0f0d3e2161e74d9907231e25d35794584b1ca5284e43f596"}, 70 | {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23e8565ab7ff33218530bc817922fae827420f143479b753104ab801145b1d5b"}, 71 | {file = "charset_normalizer-3.3.0-cp310-cp310-win32.whl", hash = "sha256:1872d01ac8c618a8da634e232f24793883d6e456a66593135aeafe3784b0848d"}, 72 | {file = "charset_normalizer-3.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:557b21a44ceac6c6b9773bc65aa1b4cc3e248a5ad2f5b914b91579a32e22204d"}, 73 | {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d7eff0f27edc5afa9e405f7165f85a6d782d308f3b6b9d96016c010597958e63"}, 74 | {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6a685067d05e46641d5d1623d7c7fdf15a357546cbb2f71b0ebde91b175ffc3e"}, 75 | {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0d3d5b7db9ed8a2b11a774db2bbea7ba1884430a205dbd54a32d61d7c2a190fa"}, 76 | {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2935ffc78db9645cb2086c2f8f4cfd23d9b73cc0dc80334bc30aac6f03f68f8c"}, 77 | {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fe359b2e3a7729010060fbca442ca225280c16e923b37db0e955ac2a2b72a05"}, 78 | {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:380c4bde80bce25c6e4f77b19386f5ec9db230df9f2f2ac1e5ad7af2caa70459"}, 79 | {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0d1e3732768fecb052d90d62b220af62ead5748ac51ef61e7b32c266cac9293"}, 80 | {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b2919306936ac6efb3aed1fbf81039f7087ddadb3160882a57ee2ff74fd2382"}, 81 | {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f8888e31e3a85943743f8fc15e71536bda1c81d5aa36d014a3c0c44481d7db6e"}, 82 | {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:82eb849f085624f6a607538ee7b83a6d8126df6d2f7d3b319cb837b289123078"}, 83 | {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7b8b8bf1189b3ba9b8de5c8db4d541b406611a71a955bbbd7385bbc45fcb786c"}, 84 | {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5adf257bd58c1b8632046bbe43ee38c04e1038e9d37de9c57a94d6bd6ce5da34"}, 85 | {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c350354efb159b8767a6244c166f66e67506e06c8924ed74669b2c70bc8735b1"}, 86 | {file = "charset_normalizer-3.3.0-cp311-cp311-win32.whl", hash = "sha256:02af06682e3590ab952599fbadac535ede5d60d78848e555aa58d0c0abbde786"}, 87 | {file = "charset_normalizer-3.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:86d1f65ac145e2c9ed71d8ffb1905e9bba3a91ae29ba55b4c46ae6fc31d7c0d4"}, 88 | {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:3b447982ad46348c02cb90d230b75ac34e9886273df3a93eec0539308a6296d7"}, 89 | {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:abf0d9f45ea5fb95051c8bfe43cb40cda383772f7e5023a83cc481ca2604d74e"}, 90 | {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b09719a17a2301178fac4470d54b1680b18a5048b481cb8890e1ef820cb80455"}, 91 | {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3d9b48ee6e3967b7901c052b670c7dda6deb812c309439adaffdec55c6d7b78"}, 92 | {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:edfe077ab09442d4ef3c52cb1f9dab89bff02f4524afc0acf2d46be17dc479f5"}, 93 | {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3debd1150027933210c2fc321527c2299118aa929c2f5a0a80ab6953e3bd1908"}, 94 | {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86f63face3a527284f7bb8a9d4f78988e3c06823f7bea2bd6f0e0e9298ca0403"}, 95 | {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24817cb02cbef7cd499f7c9a2735286b4782bd47a5b3516a0e84c50eab44b98e"}, 96 | {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c71f16da1ed8949774ef79f4a0260d28b83b3a50c6576f8f4f0288d109777989"}, 97 | {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9cf3126b85822c4e53aa28c7ec9869b924d6fcfb76e77a45c44b83d91afd74f9"}, 98 | {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:b3b2316b25644b23b54a6f6401074cebcecd1244c0b8e80111c9a3f1c8e83d65"}, 99 | {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:03680bb39035fbcffe828eae9c3f8afc0428c91d38e7d61aa992ef7a59fb120e"}, 100 | {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4cc152c5dd831641e995764f9f0b6589519f6f5123258ccaca8c6d34572fefa8"}, 101 | {file = "charset_normalizer-3.3.0-cp312-cp312-win32.whl", hash = "sha256:b8f3307af845803fb0b060ab76cf6dd3a13adc15b6b451f54281d25911eb92df"}, 102 | {file = "charset_normalizer-3.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:8eaf82f0eccd1505cf39a45a6bd0a8cf1c70dcfc30dba338207a969d91b965c0"}, 103 | {file = "charset_normalizer-3.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dc45229747b67ffc441b3de2f3ae5e62877a282ea828a5bdb67883c4ee4a8810"}, 104 | {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f4a0033ce9a76e391542c182f0d48d084855b5fcba5010f707c8e8c34663d77"}, 105 | {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ada214c6fa40f8d800e575de6b91a40d0548139e5dc457d2ebb61470abf50186"}, 106 | {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b1121de0e9d6e6ca08289583d7491e7fcb18a439305b34a30b20d8215922d43c"}, 107 | {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1063da2c85b95f2d1a430f1c33b55c9c17ffaf5e612e10aeaad641c55a9e2b9d"}, 108 | {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70f1d09c0d7748b73290b29219e854b3207aea922f839437870d8cc2168e31cc"}, 109 | {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:250c9eb0f4600361dd80d46112213dff2286231d92d3e52af1e5a6083d10cad9"}, 110 | {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:750b446b2ffce1739e8578576092179160f6d26bd5e23eb1789c4d64d5af7dc7"}, 111 | {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:fc52b79d83a3fe3a360902d3f5d79073a993597d48114c29485e9431092905d8"}, 112 | {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:588245972aca710b5b68802c8cad9edaa98589b1b42ad2b53accd6910dad3545"}, 113 | {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e39c7eb31e3f5b1f88caff88bcff1b7f8334975b46f6ac6e9fc725d829bc35d4"}, 114 | {file = "charset_normalizer-3.3.0-cp37-cp37m-win32.whl", hash = "sha256:abecce40dfebbfa6abf8e324e1860092eeca6f7375c8c4e655a8afb61af58f2c"}, 115 | {file = "charset_normalizer-3.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:24a91a981f185721542a0b7c92e9054b7ab4fea0508a795846bc5b0abf8118d4"}, 116 | {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:67b8cc9574bb518ec76dc8e705d4c39ae78bb96237cb533edac149352c1f39fe"}, 117 | {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac71b2977fb90c35d41c9453116e283fac47bb9096ad917b8819ca8b943abecd"}, 118 | {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3ae38d325b512f63f8da31f826e6cb6c367336f95e418137286ba362925c877e"}, 119 | {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:542da1178c1c6af8873e143910e2269add130a299c9106eef2594e15dae5e482"}, 120 | {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30a85aed0b864ac88309b7d94be09f6046c834ef60762a8833b660139cfbad13"}, 121 | {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aae32c93e0f64469f74ccc730a7cb21c7610af3a775157e50bbd38f816536b38"}, 122 | {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15b26ddf78d57f1d143bdf32e820fd8935d36abe8a25eb9ec0b5a71c82eb3895"}, 123 | {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f5d10bae5d78e4551b7be7a9b29643a95aded9d0f602aa2ba584f0388e7a557"}, 124 | {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:249c6470a2b60935bafd1d1d13cd613f8cd8388d53461c67397ee6a0f5dce741"}, 125 | {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c5a74c359b2d47d26cdbbc7845e9662d6b08a1e915eb015d044729e92e7050b7"}, 126 | {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:b5bcf60a228acae568e9911f410f9d9e0d43197d030ae5799e20dca8df588287"}, 127 | {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:187d18082694a29005ba2944c882344b6748d5be69e3a89bf3cc9d878e548d5a"}, 128 | {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:81bf654678e575403736b85ba3a7867e31c2c30a69bc57fe88e3ace52fb17b89"}, 129 | {file = "charset_normalizer-3.3.0-cp38-cp38-win32.whl", hash = "sha256:85a32721ddde63c9df9ebb0d2045b9691d9750cb139c161c80e500d210f5e26e"}, 130 | {file = "charset_normalizer-3.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:468d2a840567b13a590e67dd276c570f8de00ed767ecc611994c301d0f8c014f"}, 131 | {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e0fc42822278451bc13a2e8626cf2218ba570f27856b536e00cfa53099724828"}, 132 | {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:09c77f964f351a7369cc343911e0df63e762e42bac24cd7d18525961c81754f4"}, 133 | {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:12ebea541c44fdc88ccb794a13fe861cc5e35d64ed689513a5c03d05b53b7c82"}, 134 | {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:805dfea4ca10411a5296bcc75638017215a93ffb584c9e344731eef0dcfb026a"}, 135 | {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:96c2b49eb6a72c0e4991d62406e365d87067ca14c1a729a870d22354e6f68115"}, 136 | {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaf7b34c5bc56b38c931a54f7952f1ff0ae77a2e82496583b247f7c969eb1479"}, 137 | {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:619d1c96099be5823db34fe89e2582b336b5b074a7f47f819d6b3a57ff7bdb86"}, 138 | {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0ac5e7015a5920cfce654c06618ec40c33e12801711da6b4258af59a8eff00a"}, 139 | {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:93aa7eef6ee71c629b51ef873991d6911b906d7312c6e8e99790c0f33c576f89"}, 140 | {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7966951325782121e67c81299a031f4c115615e68046f79b85856b86ebffc4cd"}, 141 | {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:02673e456dc5ab13659f85196c534dc596d4ef260e4d86e856c3b2773ce09843"}, 142 | {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:c2af80fb58f0f24b3f3adcb9148e6203fa67dd3f61c4af146ecad033024dde43"}, 143 | {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:153e7b6e724761741e0974fc4dcd406d35ba70b92bfe3fedcb497226c93b9da7"}, 144 | {file = "charset_normalizer-3.3.0-cp39-cp39-win32.whl", hash = "sha256:d47ecf253780c90ee181d4d871cd655a789da937454045b17b5798da9393901a"}, 145 | {file = "charset_normalizer-3.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:d97d85fa63f315a8bdaba2af9a6a686e0eceab77b3089af45133252618e70884"}, 146 | {file = "charset_normalizer-3.3.0-py3-none-any.whl", hash = "sha256:e46cd37076971c1040fc8c41273a8b3e2c624ce4f2be3f5dfcb7a430c1d3acc2"}, 147 | ] 148 | 149 | [[package]] 150 | name = "click-spinner" 151 | version = "0.1.10" 152 | description = "Spinner for Click" 153 | optional = false 154 | python-versions = "*" 155 | files = [ 156 | {file = "click-spinner-0.1.10.tar.gz", hash = "sha256:87eacf9d7298973a25d7615ef57d4782aebf913a532bba4b28a37e366e975daf"}, 157 | {file = "click_spinner-0.1.10-py2.py3-none-any.whl", hash = "sha256:d1ffcff1fdad9882396367f15fb957bcf7f5c64ab91927dee2127e0d2991ee84"}, 158 | ] 159 | 160 | [package.extras] 161 | test = ["click", "pytest", "six"] 162 | 163 | [[package]] 164 | name = "codecov" 165 | version = "2.1.13" 166 | description = "Hosted coverage reports for GitHub, Bitbucket and Gitlab" 167 | optional = false 168 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 169 | files = [ 170 | {file = "codecov-2.1.13-py2.py3-none-any.whl", hash = "sha256:c2ca5e51bba9ebb43644c43d0690148a55086f7f5e6fd36170858fa4206744d5"}, 171 | {file = "codecov-2.1.13.tar.gz", hash = "sha256:2362b685633caeaf45b9951a9b76ce359cd3581dd515b430c6c3f5dfb4d92a8c"}, 172 | ] 173 | 174 | [package.dependencies] 175 | coverage = "*" 176 | requests = ">=2.7.9" 177 | 178 | [[package]] 179 | name = "colorama" 180 | version = "0.4.6" 181 | description = "Cross-platform colored terminal text." 182 | optional = false 183 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 184 | files = [ 185 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, 186 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, 187 | ] 188 | 189 | [[package]] 190 | name = "coverage" 191 | version = "7.2.7" 192 | description = "Code coverage measurement for Python" 193 | optional = false 194 | python-versions = ">=3.7" 195 | files = [ 196 | {file = "coverage-7.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8"}, 197 | {file = "coverage-7.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb"}, 198 | {file = "coverage-7.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6"}, 199 | {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2"}, 200 | {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063"}, 201 | {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1"}, 202 | {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353"}, 203 | {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495"}, 204 | {file = "coverage-7.2.7-cp310-cp310-win32.whl", hash = "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818"}, 205 | {file = "coverage-7.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850"}, 206 | {file = "coverage-7.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f"}, 207 | {file = "coverage-7.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe"}, 208 | {file = "coverage-7.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3"}, 209 | {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f"}, 210 | {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb"}, 211 | {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833"}, 212 | {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97"}, 213 | {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a"}, 214 | {file = "coverage-7.2.7-cp311-cp311-win32.whl", hash = "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a"}, 215 | {file = "coverage-7.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562"}, 216 | {file = "coverage-7.2.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4"}, 217 | {file = "coverage-7.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4"}, 218 | {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01"}, 219 | {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6"}, 220 | {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d"}, 221 | {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de"}, 222 | {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d"}, 223 | {file = "coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511"}, 224 | {file = "coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3"}, 225 | {file = "coverage-7.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f"}, 226 | {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb"}, 227 | {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9"}, 228 | {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd"}, 229 | {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a"}, 230 | {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959"}, 231 | {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02"}, 232 | {file = "coverage-7.2.7-cp37-cp37m-win32.whl", hash = "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f"}, 233 | {file = "coverage-7.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0"}, 234 | {file = "coverage-7.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5"}, 235 | {file = "coverage-7.2.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5"}, 236 | {file = "coverage-7.2.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9"}, 237 | {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6"}, 238 | {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e"}, 239 | {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050"}, 240 | {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5"}, 241 | {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f"}, 242 | {file = "coverage-7.2.7-cp38-cp38-win32.whl", hash = "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e"}, 243 | {file = "coverage-7.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c"}, 244 | {file = "coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9"}, 245 | {file = "coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2"}, 246 | {file = "coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7"}, 247 | {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e"}, 248 | {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1"}, 249 | {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9"}, 250 | {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250"}, 251 | {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2"}, 252 | {file = "coverage-7.2.7-cp39-cp39-win32.whl", hash = "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb"}, 253 | {file = "coverage-7.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27"}, 254 | {file = "coverage-7.2.7-pp37.pp38.pp39-none-any.whl", hash = "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d"}, 255 | {file = "coverage-7.2.7.tar.gz", hash = "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59"}, 256 | ] 257 | 258 | [package.dependencies] 259 | tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} 260 | 261 | [package.extras] 262 | toml = ["tomli"] 263 | 264 | [[package]] 265 | name = "croniter" 266 | version = "1.4.1" 267 | description = "croniter provides iteration for datetime object with cron like format" 268 | optional = false 269 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 270 | files = [ 271 | {file = "croniter-1.4.1-py2.py3-none-any.whl", hash = "sha256:9595da48af37ea06ec3a9f899738f1b2c1c13da3c38cea606ef7cd03ea421128"}, 272 | {file = "croniter-1.4.1.tar.gz", hash = "sha256:1a6df60eacec3b7a0aa52a8f2ef251ae3dd2a7c7c8b9874e73e791636d55a361"}, 273 | ] 274 | 275 | [package.dependencies] 276 | python-dateutil = "*" 277 | 278 | [[package]] 279 | name = "exceptiongroup" 280 | version = "1.1.3" 281 | description = "Backport of PEP 654 (exception groups)" 282 | optional = false 283 | python-versions = ">=3.7" 284 | files = [ 285 | {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, 286 | {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, 287 | ] 288 | 289 | [package.extras] 290 | test = ["pytest (>=6)"] 291 | 292 | [[package]] 293 | name = "fastapi" 294 | version = "0.103.2" 295 | description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" 296 | optional = false 297 | python-versions = ">=3.7" 298 | files = [ 299 | {file = "fastapi-0.103.2-py3-none-any.whl", hash = "sha256:3270de872f0fe9ec809d4bd3d4d890c6d5cc7b9611d721d6438f9dacc8c4ef2e"}, 300 | {file = "fastapi-0.103.2.tar.gz", hash = "sha256:75a11f6bfb8fc4d2bec0bd710c2d5f2829659c0e8c0afd5560fdda6ce25ec653"}, 301 | ] 302 | 303 | [package.dependencies] 304 | anyio = ">=3.7.1,<4.0.0" 305 | pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" 306 | starlette = ">=0.27.0,<0.28.0" 307 | typing-extensions = ">=4.5.0" 308 | 309 | [package.extras] 310 | all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] 311 | 312 | [[package]] 313 | name = "greenlet" 314 | version = "3.0.0" 315 | description = "Lightweight in-process concurrent programming" 316 | optional = false 317 | python-versions = ">=3.7" 318 | files = [ 319 | {file = "greenlet-3.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e09dea87cc91aea5500262993cbd484b41edf8af74f976719dd83fe724644cd6"}, 320 | {file = "greenlet-3.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f47932c434a3c8d3c86d865443fadc1fbf574e9b11d6650b656e602b1797908a"}, 321 | {file = "greenlet-3.0.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bdfaeecf8cc705d35d8e6de324bf58427d7eafb55f67050d8f28053a3d57118c"}, 322 | {file = "greenlet-3.0.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a68d670c8f89ff65c82b936275369e532772eebc027c3be68c6b87ad05ca695"}, 323 | {file = "greenlet-3.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ad562a104cd41e9d4644f46ea37167b93190c6d5e4048fcc4b80d34ecb278f"}, 324 | {file = "greenlet-3.0.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:02a807b2a58d5cdebb07050efe3d7deaf915468d112dfcf5e426d0564aa3aa4a"}, 325 | {file = "greenlet-3.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b1660a15a446206c8545edc292ab5c48b91ff732f91b3d3b30d9a915d5ec4779"}, 326 | {file = "greenlet-3.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:813720bd57e193391dfe26f4871186cf460848b83df7e23e6bef698a7624b4c9"}, 327 | {file = "greenlet-3.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:aa15a2ec737cb609ed48902b45c5e4ff6044feb5dcdfcf6fa8482379190330d7"}, 328 | {file = "greenlet-3.0.0-cp310-universal2-macosx_11_0_x86_64.whl", hash = "sha256:7709fd7bb02b31908dc8fd35bfd0a29fc24681d5cc9ac1d64ad07f8d2b7db62f"}, 329 | {file = "greenlet-3.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:211ef8d174601b80e01436f4e6905aca341b15a566f35a10dd8d1e93f5dbb3b7"}, 330 | {file = "greenlet-3.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6512592cc49b2c6d9b19fbaa0312124cd4c4c8a90d28473f86f92685cc5fef8e"}, 331 | {file = "greenlet-3.0.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:871b0a8835f9e9d461b7fdaa1b57e3492dd45398e87324c047469ce2fc9f516c"}, 332 | {file = "greenlet-3.0.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b505fcfc26f4148551826a96f7317e02c400665fa0883fe505d4fcaab1dabfdd"}, 333 | {file = "greenlet-3.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:123910c58234a8d40eaab595bc56a5ae49bdd90122dde5bdc012c20595a94c14"}, 334 | {file = "greenlet-3.0.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:96d9ea57292f636ec851a9bb961a5cc0f9976900e16e5d5647f19aa36ba6366b"}, 335 | {file = "greenlet-3.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0b72b802496cccbd9b31acea72b6f87e7771ccfd7f7927437d592e5c92ed703c"}, 336 | {file = "greenlet-3.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:527cd90ba3d8d7ae7dceb06fda619895768a46a1b4e423bdb24c1969823b8362"}, 337 | {file = "greenlet-3.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:37f60b3a42d8b5499be910d1267b24355c495064f271cfe74bf28b17b099133c"}, 338 | {file = "greenlet-3.0.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1482fba7fbed96ea7842b5a7fc11d61727e8be75a077e603e8ab49d24e234383"}, 339 | {file = "greenlet-3.0.0-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:be557119bf467d37a8099d91fbf11b2de5eb1fd5fc5b91598407574848dc910f"}, 340 | {file = "greenlet-3.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:73b2f1922a39d5d59cc0e597987300df3396b148a9bd10b76a058a2f2772fc04"}, 341 | {file = "greenlet-3.0.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1e22c22f7826096ad503e9bb681b05b8c1f5a8138469b255eb91f26a76634f2"}, 342 | {file = "greenlet-3.0.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d363666acc21d2c204dd8705c0e0457d7b2ee7a76cb16ffc099d6799744ac99"}, 343 | {file = "greenlet-3.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:334ef6ed8337bd0b58bb0ae4f7f2dcc84c9f116e474bb4ec250a8bb9bd797a66"}, 344 | {file = "greenlet-3.0.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6672fdde0fd1a60b44fb1751a7779c6db487e42b0cc65e7caa6aa686874e79fb"}, 345 | {file = "greenlet-3.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:952256c2bc5b4ee8df8dfc54fc4de330970bf5d79253c863fb5e6761f00dda35"}, 346 | {file = "greenlet-3.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:269d06fa0f9624455ce08ae0179430eea61085e3cf6457f05982b37fd2cefe17"}, 347 | {file = "greenlet-3.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:9adbd8ecf097e34ada8efde9b6fec4dd2a903b1e98037adf72d12993a1c80b51"}, 348 | {file = "greenlet-3.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6b5ce7f40f0e2f8b88c28e6691ca6806814157ff05e794cdd161be928550f4c"}, 349 | {file = "greenlet-3.0.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ecf94aa539e97a8411b5ea52fc6ccd8371be9550c4041011a091eb8b3ca1d810"}, 350 | {file = "greenlet-3.0.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80dcd3c938cbcac986c5c92779db8e8ce51a89a849c135172c88ecbdc8c056b7"}, 351 | {file = "greenlet-3.0.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e52a712c38e5fb4fd68e00dc3caf00b60cb65634d50e32281a9d6431b33b4af1"}, 352 | {file = "greenlet-3.0.0-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d5539f6da3418c3dc002739cb2bb8d169056aa66e0c83f6bacae0cd3ac26b423"}, 353 | {file = "greenlet-3.0.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:343675e0da2f3c69d3fb1e894ba0a1acf58f481f3b9372ce1eb465ef93cf6fed"}, 354 | {file = "greenlet-3.0.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:abe1ef3d780de56defd0c77c5ba95e152f4e4c4e12d7e11dd8447d338b85a625"}, 355 | {file = "greenlet-3.0.0-cp37-cp37m-win32.whl", hash = "sha256:e693e759e172fa1c2c90d35dea4acbdd1d609b6936115d3739148d5e4cd11947"}, 356 | {file = "greenlet-3.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:bdd696947cd695924aecb3870660b7545a19851f93b9d327ef8236bfc49be705"}, 357 | {file = "greenlet-3.0.0-cp37-universal2-macosx_11_0_x86_64.whl", hash = "sha256:cc3e2679ea13b4de79bdc44b25a0c4fcd5e94e21b8f290791744ac42d34a0353"}, 358 | {file = "greenlet-3.0.0-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:63acdc34c9cde42a6534518e32ce55c30f932b473c62c235a466469a710bfbf9"}, 359 | {file = "greenlet-3.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a1a6244ff96343e9994e37e5b4839f09a0207d35ef6134dce5c20d260d0302c"}, 360 | {file = "greenlet-3.0.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b822fab253ac0f330ee807e7485769e3ac85d5eef827ca224feaaefa462dc0d0"}, 361 | {file = "greenlet-3.0.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8060b32d8586e912a7b7dac2d15b28dbbd63a174ab32f5bc6d107a1c4143f40b"}, 362 | {file = "greenlet-3.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:621fcb346141ae08cb95424ebfc5b014361621b8132c48e538e34c3c93ac7365"}, 363 | {file = "greenlet-3.0.0-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6bb36985f606a7c49916eff74ab99399cdfd09241c375d5a820bb855dfb4af9f"}, 364 | {file = "greenlet-3.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:10b5582744abd9858947d163843d323d0b67be9432db50f8bf83031032bc218d"}, 365 | {file = "greenlet-3.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f351479a6914fd81a55c8e68963609f792d9b067fb8a60a042c585a621e0de4f"}, 366 | {file = "greenlet-3.0.0-cp38-cp38-win32.whl", hash = "sha256:9de687479faec7db5b198cc365bc34addd256b0028956501f4d4d5e9ca2e240a"}, 367 | {file = "greenlet-3.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:3fd2b18432e7298fcbec3d39e1a0aa91ae9ea1c93356ec089421fabc3651572b"}, 368 | {file = "greenlet-3.0.0-cp38-universal2-macosx_11_0_x86_64.whl", hash = "sha256:3c0d36f5adc6e6100aedbc976d7428a9f7194ea79911aa4bf471f44ee13a9464"}, 369 | {file = "greenlet-3.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4cd83fb8d8e17633ad534d9ac93719ef8937568d730ef07ac3a98cb520fd93e4"}, 370 | {file = "greenlet-3.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a5b2d4cdaf1c71057ff823a19d850ed5c6c2d3686cb71f73ae4d6382aaa7a06"}, 371 | {file = "greenlet-3.0.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e7dcdfad252f2ca83c685b0fa9fba00e4d8f243b73839229d56ee3d9d219314"}, 372 | {file = "greenlet-3.0.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c94e4e924d09b5a3e37b853fe5924a95eac058cb6f6fb437ebb588b7eda79870"}, 373 | {file = "greenlet-3.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad6fb737e46b8bd63156b8f59ba6cdef46fe2b7db0c5804388a2d0519b8ddb99"}, 374 | {file = "greenlet-3.0.0-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d55db1db455c59b46f794346efce896e754b8942817f46a1bada2d29446e305a"}, 375 | {file = "greenlet-3.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:56867a3b3cf26dc8a0beecdb4459c59f4c47cdd5424618c08515f682e1d46692"}, 376 | {file = "greenlet-3.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9a812224a5fb17a538207e8cf8e86f517df2080c8ee0f8c1ed2bdaccd18f38f4"}, 377 | {file = "greenlet-3.0.0-cp39-cp39-win32.whl", hash = "sha256:0d3f83ffb18dc57243e0151331e3c383b05e5b6c5029ac29f754745c800f8ed9"}, 378 | {file = "greenlet-3.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:831d6f35037cf18ca5e80a737a27d822d87cd922521d18ed3dbc8a6967be50ce"}, 379 | {file = "greenlet-3.0.0-cp39-universal2-macosx_11_0_x86_64.whl", hash = "sha256:a048293392d4e058298710a54dfaefcefdf49d287cd33fb1f7d63d55426e4355"}, 380 | {file = "greenlet-3.0.0.tar.gz", hash = "sha256:19834e3f91f485442adc1ee440171ec5d9a4840a1f7bd5ed97833544719ce10b"}, 381 | ] 382 | 383 | [package.extras] 384 | docs = ["Sphinx"] 385 | test = ["objgraph", "psutil"] 386 | 387 | [[package]] 388 | name = "h11" 389 | version = "0.14.0" 390 | description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" 391 | optional = false 392 | python-versions = ">=3.7" 393 | files = [ 394 | {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, 395 | {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, 396 | ] 397 | 398 | [package.dependencies] 399 | typing-extensions = {version = "*", markers = "python_version < \"3.8\""} 400 | 401 | [[package]] 402 | name = "httpcore" 403 | version = "0.16.3" 404 | description = "A minimal low-level HTTP client." 405 | optional = false 406 | python-versions = ">=3.7" 407 | files = [ 408 | {file = "httpcore-0.16.3-py3-none-any.whl", hash = "sha256:da1fb708784a938aa084bde4feb8317056c55037247c787bd7e19eb2c2949dc0"}, 409 | {file = "httpcore-0.16.3.tar.gz", hash = "sha256:c5d6f04e2fc530f39e0c077e6a30caa53f1451096120f1f38b954afd0b17c0cb"}, 410 | ] 411 | 412 | [package.dependencies] 413 | anyio = ">=3.0,<5.0" 414 | certifi = "*" 415 | h11 = ">=0.13,<0.15" 416 | sniffio = "==1.*" 417 | 418 | [package.extras] 419 | http2 = ["h2 (>=3,<5)"] 420 | socks = ["socksio (==1.*)"] 421 | 422 | [[package]] 423 | name = "httpx" 424 | version = "0.23.3" 425 | description = "The next generation HTTP client." 426 | optional = false 427 | python-versions = ">=3.7" 428 | files = [ 429 | {file = "httpx-0.23.3-py3-none-any.whl", hash = "sha256:a211fcce9b1254ea24f0cd6af9869b3d29aba40154e947d2a07bb499b3e310d6"}, 430 | {file = "httpx-0.23.3.tar.gz", hash = "sha256:9818458eb565bb54898ccb9b8b251a28785dd4a55afbc23d0eb410754fe7d0f9"}, 431 | ] 432 | 433 | [package.dependencies] 434 | certifi = "*" 435 | httpcore = ">=0.15.0,<0.17.0" 436 | rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]} 437 | sniffio = "*" 438 | 439 | [package.extras] 440 | brotli = ["brotli", "brotlicffi"] 441 | cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<13)"] 442 | http2 = ["h2 (>=3,<5)"] 443 | socks = ["socksio (==1.*)"] 444 | 445 | [[package]] 446 | name = "idna" 447 | version = "3.7" 448 | description = "Internationalized Domain Names in Applications (IDNA)" 449 | optional = false 450 | python-versions = ">=3.5" 451 | files = [ 452 | {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, 453 | {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, 454 | ] 455 | 456 | [[package]] 457 | name = "importlib-metadata" 458 | version = "6.7.0" 459 | description = "Read metadata from Python packages" 460 | optional = false 461 | python-versions = ">=3.7" 462 | files = [ 463 | {file = "importlib_metadata-6.7.0-py3-none-any.whl", hash = "sha256:cb52082e659e97afc5dac71e79de97d8681de3aa07ff18578330904a9d18e5b5"}, 464 | {file = "importlib_metadata-6.7.0.tar.gz", hash = "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4"}, 465 | ] 466 | 467 | [package.dependencies] 468 | typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} 469 | zipp = ">=0.5" 470 | 471 | [package.extras] 472 | docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] 473 | perf = ["ipython"] 474 | testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] 475 | 476 | [[package]] 477 | name = "iniconfig" 478 | version = "2.0.0" 479 | description = "brain-dead simple config-ini parsing" 480 | optional = false 481 | python-versions = ">=3.7" 482 | files = [ 483 | {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, 484 | {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, 485 | ] 486 | 487 | [[package]] 488 | name = "packaging" 489 | version = "23.2" 490 | description = "Core utilities for Python packages" 491 | optional = false 492 | python-versions = ">=3.7" 493 | files = [ 494 | {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, 495 | {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, 496 | ] 497 | 498 | [[package]] 499 | name = "pluggy" 500 | version = "1.2.0" 501 | description = "plugin and hook calling mechanisms for python" 502 | optional = false 503 | python-versions = ">=3.7" 504 | files = [ 505 | {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"}, 506 | {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"}, 507 | ] 508 | 509 | [package.dependencies] 510 | importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} 511 | 512 | [package.extras] 513 | dev = ["pre-commit", "tox"] 514 | testing = ["pytest", "pytest-benchmark"] 515 | 516 | [[package]] 517 | name = "pydantic" 518 | version = "2.4.2" 519 | description = "Data validation using Python type hints" 520 | optional = false 521 | python-versions = ">=3.7" 522 | files = [ 523 | {file = "pydantic-2.4.2-py3-none-any.whl", hash = "sha256:bc3ddf669d234f4220e6e1c4d96b061abe0998185a8d7855c0126782b7abc8c1"}, 524 | {file = "pydantic-2.4.2.tar.gz", hash = "sha256:94f336138093a5d7f426aac732dcfe7ab4eb4da243c88f891d65deb4a2556ee7"}, 525 | ] 526 | 527 | [package.dependencies] 528 | annotated-types = ">=0.4.0" 529 | pydantic-core = "2.10.1" 530 | typing-extensions = ">=4.6.1" 531 | 532 | [package.extras] 533 | email = ["email-validator (>=2.0.0)"] 534 | 535 | [[package]] 536 | name = "pydantic-core" 537 | version = "2.10.1" 538 | description = "" 539 | optional = false 540 | python-versions = ">=3.7" 541 | files = [ 542 | {file = "pydantic_core-2.10.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:d64728ee14e667ba27c66314b7d880b8eeb050e58ffc5fec3b7a109f8cddbd63"}, 543 | {file = "pydantic_core-2.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:48525933fea744a3e7464c19bfede85df4aba79ce90c60b94d8b6e1eddd67096"}, 544 | {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef337945bbd76cce390d1b2496ccf9f90b1c1242a3a7bc242ca4a9fc5993427a"}, 545 | {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1392e0638af203cee360495fd2cfdd6054711f2db5175b6e9c3c461b76f5175"}, 546 | {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0675ba5d22de54d07bccde38997e780044dcfa9a71aac9fd7d4d7a1d2e3e65f7"}, 547 | {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:128552af70a64660f21cb0eb4876cbdadf1a1f9d5de820fed6421fa8de07c893"}, 548 | {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f6e6aed5818c264412ac0598b581a002a9f050cb2637a84979859e70197aa9e"}, 549 | {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ecaac27da855b8d73f92123e5f03612b04c5632fd0a476e469dfc47cd37d6b2e"}, 550 | {file = "pydantic_core-2.10.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b3c01c2fb081fced3bbb3da78510693dc7121bb893a1f0f5f4b48013201f362e"}, 551 | {file = "pydantic_core-2.10.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:92f675fefa977625105708492850bcbc1182bfc3e997f8eecb866d1927c98ae6"}, 552 | {file = "pydantic_core-2.10.1-cp310-none-win32.whl", hash = "sha256:420a692b547736a8d8703c39ea935ab5d8f0d2573f8f123b0a294e49a73f214b"}, 553 | {file = "pydantic_core-2.10.1-cp310-none-win_amd64.whl", hash = "sha256:0880e239827b4b5b3e2ce05e6b766a7414e5f5aedc4523be6b68cfbc7f61c5d0"}, 554 | {file = "pydantic_core-2.10.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:073d4a470b195d2b2245d0343569aac7e979d3a0dcce6c7d2af6d8a920ad0bea"}, 555 | {file = "pydantic_core-2.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:600d04a7b342363058b9190d4e929a8e2e715c5682a70cc37d5ded1e0dd370b4"}, 556 | {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39215d809470f4c8d1881758575b2abfb80174a9e8daf8f33b1d4379357e417c"}, 557 | {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eeb3d3d6b399ffe55f9a04e09e635554012f1980696d6b0aca3e6cf42a17a03b"}, 558 | {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a7902bf75779bc12ccfc508bfb7a4c47063f748ea3de87135d433a4cca7a2f"}, 559 | {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3625578b6010c65964d177626fde80cf60d7f2e297d56b925cb5cdeda6e9925a"}, 560 | {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:caa48fc31fc7243e50188197b5f0c4228956f97b954f76da157aae7f67269ae8"}, 561 | {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:07ec6d7d929ae9c68f716195ce15e745b3e8fa122fc67698ac6498d802ed0fa4"}, 562 | {file = "pydantic_core-2.10.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e6f31a17acede6a8cd1ae2d123ce04d8cca74056c9d456075f4f6f85de055607"}, 563 | {file = "pydantic_core-2.10.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d8f1ebca515a03e5654f88411420fea6380fc841d1bea08effb28184e3d4899f"}, 564 | {file = "pydantic_core-2.10.1-cp311-none-win32.whl", hash = "sha256:6db2eb9654a85ada248afa5a6db5ff1cf0f7b16043a6b070adc4a5be68c716d6"}, 565 | {file = "pydantic_core-2.10.1-cp311-none-win_amd64.whl", hash = "sha256:4a5be350f922430997f240d25f8219f93b0c81e15f7b30b868b2fddfc2d05f27"}, 566 | {file = "pydantic_core-2.10.1-cp311-none-win_arm64.whl", hash = "sha256:5fdb39f67c779b183b0c853cd6b45f7db84b84e0571b3ef1c89cdb1dfc367325"}, 567 | {file = "pydantic_core-2.10.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:b1f22a9ab44de5f082216270552aa54259db20189e68fc12484873d926426921"}, 568 | {file = "pydantic_core-2.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8572cadbf4cfa95fb4187775b5ade2eaa93511f07947b38f4cd67cf10783b118"}, 569 | {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db9a28c063c7c00844ae42a80203eb6d2d6bbb97070cfa00194dff40e6f545ab"}, 570 | {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e2a35baa428181cb2270a15864ec6286822d3576f2ed0f4cd7f0c1708472aff"}, 571 | {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05560ab976012bf40f25d5225a58bfa649bb897b87192a36c6fef1ab132540d7"}, 572 | {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6495008733c7521a89422d7a68efa0a0122c99a5861f06020ef5b1f51f9ba7c"}, 573 | {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ac492c686defc8e6133e3a2d9eaf5261b3df26b8ae97450c1647286750b901"}, 574 | {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8282bab177a9a3081fd3d0a0175a07a1e2bfb7fcbbd949519ea0980f8a07144d"}, 575 | {file = "pydantic_core-2.10.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:aafdb89fdeb5fe165043896817eccd6434aee124d5ee9b354f92cd574ba5e78f"}, 576 | {file = "pydantic_core-2.10.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f6defd966ca3b187ec6c366604e9296f585021d922e666b99c47e78738b5666c"}, 577 | {file = "pydantic_core-2.10.1-cp312-none-win32.whl", hash = "sha256:7c4d1894fe112b0864c1fa75dffa045720a194b227bed12f4be7f6045b25209f"}, 578 | {file = "pydantic_core-2.10.1-cp312-none-win_amd64.whl", hash = "sha256:5994985da903d0b8a08e4935c46ed8daf5be1cf217489e673910951dc533d430"}, 579 | {file = "pydantic_core-2.10.1-cp312-none-win_arm64.whl", hash = "sha256:0d8a8adef23d86d8eceed3e32e9cca8879c7481c183f84ed1a8edc7df073af94"}, 580 | {file = "pydantic_core-2.10.1-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:9badf8d45171d92387410b04639d73811b785b5161ecadabf056ea14d62d4ede"}, 581 | {file = "pydantic_core-2.10.1-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:ebedb45b9feb7258fac0a268a3f6bec0a2ea4d9558f3d6f813f02ff3a6dc6698"}, 582 | {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfe1090245c078720d250d19cb05d67e21a9cd7c257698ef139bc41cf6c27b4f"}, 583 | {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e357571bb0efd65fd55f18db0a2fb0ed89d0bb1d41d906b138f088933ae618bb"}, 584 | {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b3dcd587b69bbf54fc04ca157c2323b8911033e827fffaecf0cafa5a892a0904"}, 585 | {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c120c9ce3b163b985a3b966bb701114beb1da4b0468b9b236fc754783d85aa3"}, 586 | {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15d6bca84ffc966cc9976b09a18cf9543ed4d4ecbd97e7086f9ce9327ea48891"}, 587 | {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5cabb9710f09d5d2e9e2748c3e3e20d991a4c5f96ed8f1132518f54ab2967221"}, 588 | {file = "pydantic_core-2.10.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:82f55187a5bebae7d81d35b1e9aaea5e169d44819789837cdd4720d768c55d15"}, 589 | {file = "pydantic_core-2.10.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1d40f55222b233e98e3921df7811c27567f0e1a4411b93d4c5c0f4ce131bc42f"}, 590 | {file = "pydantic_core-2.10.1-cp37-none-win32.whl", hash = "sha256:14e09ff0b8fe6e46b93d36a878f6e4a3a98ba5303c76bb8e716f4878a3bee92c"}, 591 | {file = "pydantic_core-2.10.1-cp37-none-win_amd64.whl", hash = "sha256:1396e81b83516b9d5c9e26a924fa69164156c148c717131f54f586485ac3c15e"}, 592 | {file = "pydantic_core-2.10.1-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:6835451b57c1b467b95ffb03a38bb75b52fb4dc2762bb1d9dbed8de31ea7d0fc"}, 593 | {file = "pydantic_core-2.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b00bc4619f60c853556b35f83731bd817f989cba3e97dc792bb8c97941b8053a"}, 594 | {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fa467fd300a6f046bdb248d40cd015b21b7576c168a6bb20aa22e595c8ffcdd"}, 595 | {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d99277877daf2efe074eae6338453a4ed54a2d93fb4678ddfe1209a0c93a2468"}, 596 | {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa7db7558607afeccb33c0e4bf1c9a9a835e26599e76af6fe2fcea45904083a6"}, 597 | {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aad7bd686363d1ce4ee930ad39f14e1673248373f4a9d74d2b9554f06199fb58"}, 598 | {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:443fed67d33aa85357464f297e3d26e570267d1af6fef1c21ca50921d2976302"}, 599 | {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:042462d8d6ba707fd3ce9649e7bf268633a41018d6a998fb5fbacb7e928a183e"}, 600 | {file = "pydantic_core-2.10.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ecdbde46235f3d560b18be0cb706c8e8ad1b965e5c13bbba7450c86064e96561"}, 601 | {file = "pydantic_core-2.10.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ed550ed05540c03f0e69e6d74ad58d026de61b9eaebebbaaf8873e585cbb18de"}, 602 | {file = "pydantic_core-2.10.1-cp38-none-win32.whl", hash = "sha256:8cdbbd92154db2fec4ec973d45c565e767ddc20aa6dbaf50142676484cbff8ee"}, 603 | {file = "pydantic_core-2.10.1-cp38-none-win_amd64.whl", hash = "sha256:9f6f3e2598604956480f6c8aa24a3384dbf6509fe995d97f6ca6103bb8c2534e"}, 604 | {file = "pydantic_core-2.10.1-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:655f8f4c8d6a5963c9a0687793da37b9b681d9ad06f29438a3b2326d4e6b7970"}, 605 | {file = "pydantic_core-2.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e570ffeb2170e116a5b17e83f19911020ac79d19c96f320cbfa1fa96b470185b"}, 606 | {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64322bfa13e44c6c30c518729ef08fda6026b96d5c0be724b3c4ae4da939f875"}, 607 | {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:485a91abe3a07c3a8d1e082ba29254eea3e2bb13cbbd4351ea4e5a21912cc9b0"}, 608 | {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7c2b8eb9fc872e68b46eeaf835e86bccc3a58ba57d0eedc109cbb14177be531"}, 609 | {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a5cb87bdc2e5f620693148b5f8f842d293cae46c5f15a1b1bf7ceeed324a740c"}, 610 | {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25bd966103890ccfa028841a8f30cebcf5875eeac8c4bde4fe221364c92f0c9a"}, 611 | {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f323306d0556351735b54acbf82904fe30a27b6a7147153cbe6e19aaaa2aa429"}, 612 | {file = "pydantic_core-2.10.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0c27f38dc4fbf07b358b2bc90edf35e82d1703e22ff2efa4af4ad5de1b3833e7"}, 613 | {file = "pydantic_core-2.10.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f1365e032a477c1430cfe0cf2856679529a2331426f8081172c4a74186f1d595"}, 614 | {file = "pydantic_core-2.10.1-cp39-none-win32.whl", hash = "sha256:a1c311fd06ab3b10805abb72109f01a134019739bd3286b8ae1bc2fc4e50c07a"}, 615 | {file = "pydantic_core-2.10.1-cp39-none-win_amd64.whl", hash = "sha256:ae8a8843b11dc0b03b57b52793e391f0122e740de3df1474814c700d2622950a"}, 616 | {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d43002441932f9a9ea5d6f9efaa2e21458221a3a4b417a14027a1d530201ef1b"}, 617 | {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fcb83175cc4936a5425dde3356f079ae03c0802bbdf8ff82c035f8a54b333521"}, 618 | {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:962ed72424bf1f72334e2f1e61b68f16c0e596f024ca7ac5daf229f7c26e4208"}, 619 | {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cf5bb4dd67f20f3bbc1209ef572a259027c49e5ff694fa56bed62959b41e1f9"}, 620 | {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e544246b859f17373bed915182ab841b80849ed9cf23f1f07b73b7c58baee5fb"}, 621 | {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c0877239307b7e69d025b73774e88e86ce82f6ba6adf98f41069d5b0b78bd1bf"}, 622 | {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:53df009d1e1ba40f696f8995683e067e3967101d4bb4ea6f667931b7d4a01357"}, 623 | {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a1254357f7e4c82e77c348dabf2d55f1d14d19d91ff025004775e70a6ef40ada"}, 624 | {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:524ff0ca3baea164d6d93a32c58ac79eca9f6cf713586fdc0adb66a8cdeab96a"}, 625 | {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f0ac9fb8608dbc6eaf17956bf623c9119b4db7dbb511650910a82e261e6600f"}, 626 | {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:320f14bd4542a04ab23747ff2c8a778bde727158b606e2661349557f0770711e"}, 627 | {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:63974d168b6233b4ed6a0046296803cb13c56637a7b8106564ab575926572a55"}, 628 | {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:417243bf599ba1f1fef2bb8c543ceb918676954734e2dcb82bf162ae9d7bd514"}, 629 | {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:dda81e5ec82485155a19d9624cfcca9be88a405e2857354e5b089c2a982144b2"}, 630 | {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:14cfbb00959259e15d684505263d5a21732b31248a5dd4941f73a3be233865b9"}, 631 | {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:631cb7415225954fdcc2a024119101946793e5923f6c4d73a5914d27eb3d3a05"}, 632 | {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:bec7dd208a4182e99c5b6c501ce0b1f49de2802448d4056091f8e630b28e9a52"}, 633 | {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:149b8a07712f45b332faee1a2258d8ef1fb4a36f88c0c17cb687f205c5dc6e7d"}, 634 | {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d966c47f9dd73c2d32a809d2be529112d509321c5310ebf54076812e6ecd884"}, 635 | {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7eb037106f5c6b3b0b864ad226b0b7ab58157124161d48e4b30c4a43fef8bc4b"}, 636 | {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:154ea7c52e32dce13065dbb20a4a6f0cc012b4f667ac90d648d36b12007fa9f7"}, 637 | {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e562617a45b5a9da5be4abe72b971d4f00bf8555eb29bb91ec2ef2be348cd132"}, 638 | {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:f23b55eb5464468f9e0e9a9935ce3ed2a870608d5f534025cd5536bca25b1402"}, 639 | {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:e9121b4009339b0f751955baf4543a0bfd6bc3f8188f8056b1a25a2d45099934"}, 640 | {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:0523aeb76e03f753b58be33b26540880bac5aa54422e4462404c432230543f33"}, 641 | {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e0e2959ef5d5b8dc9ef21e1a305a21a36e254e6a34432d00c72a92fdc5ecda5"}, 642 | {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da01bec0a26befab4898ed83b362993c844b9a607a86add78604186297eb047e"}, 643 | {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f2e9072d71c1f6cfc79a36d4484c82823c560e6f5599c43c1ca6b5cdbd54f881"}, 644 | {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f36a3489d9e28fe4b67be9992a23029c3cec0babc3bd9afb39f49844a8c721c5"}, 645 | {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f64f82cc3443149292b32387086d02a6c7fb39b8781563e0ca7b8d7d9cf72bd7"}, 646 | {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b4a6db486ac8e99ae696e09efc8b2b9fea67b63c8f88ba7a1a16c24a057a0776"}, 647 | {file = "pydantic_core-2.10.1.tar.gz", hash = "sha256:0f8682dbdd2f67f8e1edddcbffcc29f60a6182b4901c367fc8c1c40d30bb0a82"}, 648 | ] 649 | 650 | [package.dependencies] 651 | typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" 652 | 653 | [[package]] 654 | name = "pytest" 655 | version = "7.4.2" 656 | description = "pytest: simple powerful testing with Python" 657 | optional = false 658 | python-versions = ">=3.7" 659 | files = [ 660 | {file = "pytest-7.4.2-py3-none-any.whl", hash = "sha256:1d881c6124e08ff0a1bb75ba3ec0bfd8b5354a01c194ddd5a0a870a48d99b002"}, 661 | {file = "pytest-7.4.2.tar.gz", hash = "sha256:a766259cfab564a2ad52cb1aae1b881a75c3eb7e34ca3779697c23ed47c47069"}, 662 | ] 663 | 664 | [package.dependencies] 665 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 666 | exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} 667 | importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} 668 | iniconfig = "*" 669 | packaging = "*" 670 | pluggy = ">=0.12,<2.0" 671 | tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} 672 | 673 | [package.extras] 674 | testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] 675 | 676 | [[package]] 677 | name = "pytest-asyncio" 678 | version = "0.21.1" 679 | description = "Pytest support for asyncio" 680 | optional = false 681 | python-versions = ">=3.7" 682 | files = [ 683 | {file = "pytest-asyncio-0.21.1.tar.gz", hash = "sha256:40a7eae6dded22c7b604986855ea48400ab15b069ae38116e8c01238e9eeb64d"}, 684 | {file = "pytest_asyncio-0.21.1-py3-none-any.whl", hash = "sha256:8666c1c8ac02631d7c51ba282e0c69a8a452b211ffedf2599099845da5c5c37b"}, 685 | ] 686 | 687 | [package.dependencies] 688 | pytest = ">=7.0.0" 689 | typing-extensions = {version = ">=3.7.2", markers = "python_version < \"3.8\""} 690 | 691 | [package.extras] 692 | docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] 693 | testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"] 694 | 695 | [[package]] 696 | name = "pytest-cov" 697 | version = "4.1.0" 698 | description = "Pytest plugin for measuring coverage." 699 | optional = false 700 | python-versions = ">=3.7" 701 | files = [ 702 | {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, 703 | {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, 704 | ] 705 | 706 | [package.dependencies] 707 | coverage = {version = ">=5.2.1", extras = ["toml"]} 708 | pytest = ">=4.6" 709 | 710 | [package.extras] 711 | testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] 712 | 713 | [[package]] 714 | name = "python-dateutil" 715 | version = "2.8.2" 716 | description = "Extensions to the standard Python datetime module" 717 | optional = false 718 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" 719 | files = [ 720 | {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, 721 | {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, 722 | ] 723 | 724 | [package.dependencies] 725 | six = ">=1.5" 726 | 727 | [[package]] 728 | name = "requests" 729 | version = "2.31.0" 730 | description = "Python HTTP for Humans." 731 | optional = false 732 | python-versions = ">=3.7" 733 | files = [ 734 | {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, 735 | {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, 736 | ] 737 | 738 | [package.dependencies] 739 | certifi = ">=2017.4.17" 740 | charset-normalizer = ">=2,<4" 741 | idna = ">=2.5,<4" 742 | urllib3 = ">=1.21.1,<3" 743 | 744 | [package.extras] 745 | socks = ["PySocks (>=1.5.6,!=1.5.7)"] 746 | use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] 747 | 748 | [[package]] 749 | name = "rfc3986" 750 | version = "1.5.0" 751 | description = "Validating URI References per RFC 3986" 752 | optional = false 753 | python-versions = "*" 754 | files = [ 755 | {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, 756 | {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"}, 757 | ] 758 | 759 | [package.dependencies] 760 | idna = {version = "*", optional = true, markers = "extra == \"idna2008\""} 761 | 762 | [package.extras] 763 | idna2008 = ["idna"] 764 | 765 | [[package]] 766 | name = "six" 767 | version = "1.16.0" 768 | description = "Python 2 and 3 compatibility utilities" 769 | optional = false 770 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 771 | files = [ 772 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, 773 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, 774 | ] 775 | 776 | [[package]] 777 | name = "sniffio" 778 | version = "1.3.0" 779 | description = "Sniff out which async library your code is running under" 780 | optional = false 781 | python-versions = ">=3.7" 782 | files = [ 783 | {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, 784 | {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, 785 | ] 786 | 787 | [[package]] 788 | name = "sqlalchemy" 789 | version = "2.0.21" 790 | description = "Database Abstraction Library" 791 | optional = false 792 | python-versions = ">=3.7" 793 | files = [ 794 | {file = "SQLAlchemy-2.0.21-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1e7dc99b23e33c71d720c4ae37ebb095bebebbd31a24b7d99dfc4753d2803ede"}, 795 | {file = "SQLAlchemy-2.0.21-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7f0c4ee579acfe6c994637527c386d1c22eb60bc1c1d36d940d8477e482095d4"}, 796 | {file = "SQLAlchemy-2.0.21-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f7d57a7e140efe69ce2d7b057c3f9a595f98d0bbdfc23fd055efdfbaa46e3a5"}, 797 | {file = "SQLAlchemy-2.0.21-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ca38746eac23dd7c20bec9278d2058c7ad662b2f1576e4c3dbfcd7c00cc48fa"}, 798 | {file = "SQLAlchemy-2.0.21-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3cf229704074bce31f7f47d12883afee3b0a02bb233a0ba45ddbfe542939cca4"}, 799 | {file = "SQLAlchemy-2.0.21-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fb87f763b5d04a82ae84ccff25554ffd903baafba6698e18ebaf32561f2fe4aa"}, 800 | {file = "SQLAlchemy-2.0.21-cp310-cp310-win32.whl", hash = "sha256:89e274604abb1a7fd5c14867a412c9d49c08ccf6ce3e1e04fffc068b5b6499d4"}, 801 | {file = "SQLAlchemy-2.0.21-cp310-cp310-win_amd64.whl", hash = "sha256:e36339a68126ffb708dc6d1948161cea2a9e85d7d7b0c54f6999853d70d44430"}, 802 | {file = "SQLAlchemy-2.0.21-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bf8eebccc66829010f06fbd2b80095d7872991bfe8415098b9fe47deaaa58063"}, 803 | {file = "SQLAlchemy-2.0.21-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b977bfce15afa53d9cf6a632482d7968477625f030d86a109f7bdfe8ce3c064a"}, 804 | {file = "SQLAlchemy-2.0.21-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ff3dc2f60dbf82c9e599c2915db1526d65415be323464f84de8db3e361ba5b9"}, 805 | {file = "SQLAlchemy-2.0.21-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44ac5c89b6896f4740e7091f4a0ff2e62881da80c239dd9408f84f75a293dae9"}, 806 | {file = "SQLAlchemy-2.0.21-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:87bf91ebf15258c4701d71dcdd9c4ba39521fb6a37379ea68088ce8cd869b446"}, 807 | {file = "SQLAlchemy-2.0.21-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b69f1f754d92eb1cc6b50938359dead36b96a1dcf11a8670bff65fd9b21a4b09"}, 808 | {file = "SQLAlchemy-2.0.21-cp311-cp311-win32.whl", hash = "sha256:af520a730d523eab77d754f5cf44cc7dd7ad2d54907adeb3233177eeb22f271b"}, 809 | {file = "SQLAlchemy-2.0.21-cp311-cp311-win_amd64.whl", hash = "sha256:141675dae56522126986fa4ca713739d00ed3a6f08f3c2eb92c39c6dfec463ce"}, 810 | {file = "SQLAlchemy-2.0.21-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:56628ca27aa17b5890391ded4e385bf0480209726f198799b7e980c6bd473bd7"}, 811 | {file = "SQLAlchemy-2.0.21-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:db726be58837fe5ac39859e0fa40baafe54c6d54c02aba1d47d25536170b690f"}, 812 | {file = "SQLAlchemy-2.0.21-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7421c1bfdbb7214313919472307be650bd45c4dc2fcb317d64d078993de045b"}, 813 | {file = "SQLAlchemy-2.0.21-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:632784f7a6f12cfa0e84bf2a5003b07660addccf5563c132cd23b7cc1d7371a9"}, 814 | {file = "SQLAlchemy-2.0.21-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f6f7276cf26145a888f2182a98f204541b519d9ea358a65d82095d9c9e22f917"}, 815 | {file = "SQLAlchemy-2.0.21-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2a1f7ffac934bc0ea717fa1596f938483fb8c402233f9b26679b4f7b38d6ab6e"}, 816 | {file = "SQLAlchemy-2.0.21-cp312-cp312-win32.whl", hash = "sha256:bfece2f7cec502ec5f759bbc09ce711445372deeac3628f6fa1c16b7fb45b682"}, 817 | {file = "SQLAlchemy-2.0.21-cp312-cp312-win_amd64.whl", hash = "sha256:526b869a0f4f000d8d8ee3409d0becca30ae73f494cbb48801da0129601f72c6"}, 818 | {file = "SQLAlchemy-2.0.21-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7614f1eab4336df7dd6bee05bc974f2b02c38d3d0c78060c5faa4cd1ca2af3b8"}, 819 | {file = "SQLAlchemy-2.0.21-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d59cb9e20d79686aa473e0302e4a82882d7118744d30bb1dfb62d3c47141b3ec"}, 820 | {file = "SQLAlchemy-2.0.21-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a95aa0672e3065d43c8aa80080cdd5cc40fe92dc873749e6c1cf23914c4b83af"}, 821 | {file = "SQLAlchemy-2.0.21-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8c323813963b2503e54d0944813cd479c10c636e3ee223bcbd7bd478bf53c178"}, 822 | {file = "SQLAlchemy-2.0.21-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:419b1276b55925b5ac9b4c7044e999f1787c69761a3c9756dec6e5c225ceca01"}, 823 | {file = "SQLAlchemy-2.0.21-cp37-cp37m-win32.whl", hash = "sha256:4615623a490e46be85fbaa6335f35cf80e61df0783240afe7d4f544778c315a9"}, 824 | {file = "SQLAlchemy-2.0.21-cp37-cp37m-win_amd64.whl", hash = "sha256:cca720d05389ab1a5877ff05af96551e58ba65e8dc65582d849ac83ddde3e231"}, 825 | {file = "SQLAlchemy-2.0.21-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b4eae01faee9f2b17f08885e3f047153ae0416648f8e8c8bd9bc677c5ce64be9"}, 826 | {file = "SQLAlchemy-2.0.21-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3eb7c03fe1cd3255811cd4e74db1ab8dca22074d50cd8937edf4ef62d758cdf4"}, 827 | {file = "SQLAlchemy-2.0.21-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2d494b6a2a2d05fb99f01b84cc9af9f5f93bf3e1e5dbdafe4bed0c2823584c1"}, 828 | {file = "SQLAlchemy-2.0.21-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b19ae41ef26c01a987e49e37c77b9ad060c59f94d3b3efdfdbf4f3daaca7b5fe"}, 829 | {file = "SQLAlchemy-2.0.21-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:fc6b15465fabccc94bf7e38777d665b6a4f95efd1725049d6184b3a39fd54880"}, 830 | {file = "SQLAlchemy-2.0.21-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:014794b60d2021cc8ae0f91d4d0331fe92691ae5467a00841f7130fe877b678e"}, 831 | {file = "SQLAlchemy-2.0.21-cp38-cp38-win32.whl", hash = "sha256:0268256a34806e5d1c8f7ee93277d7ea8cc8ae391f487213139018b6805aeaf6"}, 832 | {file = "SQLAlchemy-2.0.21-cp38-cp38-win_amd64.whl", hash = "sha256:73c079e21d10ff2be54a4699f55865d4b275fd6c8bd5d90c5b1ef78ae0197301"}, 833 | {file = "SQLAlchemy-2.0.21-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:785e2f2c1cb50d0a44e2cdeea5fd36b5bf2d79c481c10f3a88a8be4cfa2c4615"}, 834 | {file = "SQLAlchemy-2.0.21-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c111cd40910ffcb615b33605fc8f8e22146aeb7933d06569ac90f219818345ef"}, 835 | {file = "SQLAlchemy-2.0.21-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9cba4e7369de663611ce7460a34be48e999e0bbb1feb9130070f0685e9a6b66"}, 836 | {file = "SQLAlchemy-2.0.21-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50a69067af86ec7f11a8e50ba85544657b1477aabf64fa447fd3736b5a0a4f67"}, 837 | {file = "SQLAlchemy-2.0.21-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ccb99c3138c9bde118b51a289d90096a3791658da9aea1754667302ed6564f6e"}, 838 | {file = "SQLAlchemy-2.0.21-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:513fd5b6513d37e985eb5b7ed89da5fd9e72354e3523980ef00d439bc549c9e9"}, 839 | {file = "SQLAlchemy-2.0.21-cp39-cp39-win32.whl", hash = "sha256:f9fefd6298433b6e9188252f3bff53b9ff0443c8fde27298b8a2b19f6617eeb9"}, 840 | {file = "SQLAlchemy-2.0.21-cp39-cp39-win_amd64.whl", hash = "sha256:2e617727fe4091cedb3e4409b39368f424934c7faa78171749f704b49b4bb4ce"}, 841 | {file = "SQLAlchemy-2.0.21-py3-none-any.whl", hash = "sha256:ea7da25ee458d8f404b93eb073116156fd7d8c2a776d8311534851f28277b4ce"}, 842 | {file = "SQLAlchemy-2.0.21.tar.gz", hash = "sha256:05b971ab1ac2994a14c56b35eaaa91f86ba080e9ad481b20d99d77f381bb6258"}, 843 | ] 844 | 845 | [package.dependencies] 846 | greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""} 847 | importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} 848 | typing-extensions = ">=4.2.0" 849 | 850 | [package.extras] 851 | aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"] 852 | aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing-extensions (!=3.10.0.1)"] 853 | asyncio = ["greenlet (!=0.4.17)"] 854 | asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"] 855 | mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"] 856 | mssql = ["pyodbc"] 857 | mssql-pymssql = ["pymssql"] 858 | mssql-pyodbc = ["pyodbc"] 859 | mypy = ["mypy (>=0.910)"] 860 | mysql = ["mysqlclient (>=1.4.0)"] 861 | mysql-connector = ["mysql-connector-python"] 862 | oracle = ["cx-oracle (>=7)"] 863 | oracle-oracledb = ["oracledb (>=1.0.1)"] 864 | postgresql = ["psycopg2 (>=2.7)"] 865 | postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] 866 | postgresql-pg8000 = ["pg8000 (>=1.29.1)"] 867 | postgresql-psycopg = ["psycopg (>=3.0.7)"] 868 | postgresql-psycopg2binary = ["psycopg2-binary"] 869 | postgresql-psycopg2cffi = ["psycopg2cffi"] 870 | postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] 871 | pymysql = ["pymysql"] 872 | sqlcipher = ["sqlcipher3-binary"] 873 | 874 | [[package]] 875 | name = "starlette" 876 | version = "0.27.0" 877 | description = "The little ASGI library that shines." 878 | optional = false 879 | python-versions = ">=3.7" 880 | files = [ 881 | {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"}, 882 | {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"}, 883 | ] 884 | 885 | [package.dependencies] 886 | anyio = ">=3.4.0,<5" 887 | typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} 888 | 889 | [package.extras] 890 | full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"] 891 | 892 | [[package]] 893 | name = "tomli" 894 | version = "2.0.1" 895 | description = "A lil' TOML parser" 896 | optional = false 897 | python-versions = ">=3.7" 898 | files = [ 899 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, 900 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, 901 | ] 902 | 903 | [[package]] 904 | name = "typing-extensions" 905 | version = "4.7.1" 906 | description = "Backported and Experimental Type Hints for Python 3.7+" 907 | optional = false 908 | python-versions = ">=3.7" 909 | files = [ 910 | {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, 911 | {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, 912 | ] 913 | 914 | [[package]] 915 | name = "urllib3" 916 | version = "2.0.7" 917 | description = "HTTP library with thread-safe connection pooling, file post, and more." 918 | optional = false 919 | python-versions = ">=3.7" 920 | files = [ 921 | {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"}, 922 | {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"}, 923 | ] 924 | 925 | [package.extras] 926 | brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] 927 | secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] 928 | socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] 929 | zstd = ["zstandard (>=0.18.0)"] 930 | 931 | [[package]] 932 | name = "zipp" 933 | version = "3.15.0" 934 | description = "Backport of pathlib-compatible object wrapper for zip files" 935 | optional = false 936 | python-versions = ">=3.7" 937 | files = [ 938 | {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, 939 | {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, 940 | ] 941 | 942 | [package.extras] 943 | docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] 944 | testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] 945 | 946 | [metadata] 947 | lock-version = "2.0" 948 | python-versions = "^3.7" 949 | content-hash = "91d96213c107d8fe19972fec208d5f1e80dbf80c67309bb0528fadbf2779b101" 950 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "fastapi-utilities" 3 | version = "0.3.1" 4 | description = "Reusable utilities for FastAPI" 5 | authors = ["Priyanshu Panwar "] 6 | readme = "README.md" 7 | keywords = ["fastapi", "utilities", "utils", "fastapi-utilities", "python", "library", "framework", "web", "api"] 8 | license = "MIT" 9 | classifiers = [ 10 | "Programming Language :: Python :: 3 :: Only", 11 | "Programming Language :: Python :: 3.7", 12 | "Programming Language :: Python :: 3.8", 13 | "Programming Language :: Python :: 3.9", 14 | "Programming Language :: Python :: 3.10", 15 | "Programming Language :: Python :: 3.11", 16 | "Programming Language :: Python :: 3.12", 17 | "License :: OSI Approved :: MIT License", 18 | "Operating System :: OS Independent", 19 | "Development Status :: 3 - Alpha", 20 | "Intended Audience :: Developers", 21 | "Topic :: Software Development :: Libraries :: Python Modules", 22 | "Topic :: Utilities", 23 | "Framework :: AsyncIO", 24 | "Framework :: FastAPI", 25 | "Topic :: Internet :: WWW/HTTP :: HTTP Servers", 26 | "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", 27 | "Topic :: Internet :: WWW/HTTP :: WSGI :: Server", 28 | ] 29 | 30 | [tool.poetry.dependencies] 31 | python = "^3.7" 32 | fastapi = "*" 33 | pydantic = "*" 34 | sqlalchemy = "*" 35 | croniter = "^1.0.13" 36 | click-spinner = "^0.1.10" 37 | 38 | [tool.poetry.group.dev.dependencies] 39 | pytest = "*" 40 | pytest-cov = "*" 41 | pytest-asyncio = "^0.21.1" 42 | codecov = "^2.1.13" 43 | httpx = "0.23.3" 44 | 45 | [build-system] 46 | requires = ["poetry-core"] 47 | build-backend = "poetry.core.masonry.api" 48 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | annotated-types==0.5.0 ; python_version >= "3.7" and python_version < "4.0" \ 2 | --hash=sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802 \ 3 | --hash=sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd 4 | anyio==3.7.1 ; python_version >= "3.7" and python_version < "4.0" \ 5 | --hash=sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780 \ 6 | --hash=sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5 7 | certifi==2023.7.22 ; python_version >= "3.7" and python_version < "4.0" \ 8 | --hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \ 9 | --hash=sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9 10 | charset-normalizer==3.3.0 ; python_version >= "3.7" and python_version < "4.0" \ 11 | --hash=sha256:02673e456dc5ab13659f85196c534dc596d4ef260e4d86e856c3b2773ce09843 \ 12 | --hash=sha256:02af06682e3590ab952599fbadac535ede5d60d78848e555aa58d0c0abbde786 \ 13 | --hash=sha256:03680bb39035fbcffe828eae9c3f8afc0428c91d38e7d61aa992ef7a59fb120e \ 14 | --hash=sha256:0570d21da019941634a531444364f2482e8db0b3425fcd5ac0c36565a64142c8 \ 15 | --hash=sha256:09c77f964f351a7369cc343911e0df63e762e42bac24cd7d18525961c81754f4 \ 16 | --hash=sha256:0d3d5b7db9ed8a2b11a774db2bbea7ba1884430a205dbd54a32d61d7c2a190fa \ 17 | --hash=sha256:1063da2c85b95f2d1a430f1c33b55c9c17ffaf5e612e10aeaad641c55a9e2b9d \ 18 | --hash=sha256:12ebea541c44fdc88ccb794a13fe861cc5e35d64ed689513a5c03d05b53b7c82 \ 19 | --hash=sha256:153e7b6e724761741e0974fc4dcd406d35ba70b92bfe3fedcb497226c93b9da7 \ 20 | --hash=sha256:15b26ddf78d57f1d143bdf32e820fd8935d36abe8a25eb9ec0b5a71c82eb3895 \ 21 | --hash=sha256:1872d01ac8c618a8da634e232f24793883d6e456a66593135aeafe3784b0848d \ 22 | --hash=sha256:187d18082694a29005ba2944c882344b6748d5be69e3a89bf3cc9d878e548d5a \ 23 | --hash=sha256:1b2919306936ac6efb3aed1fbf81039f7087ddadb3160882a57ee2ff74fd2382 \ 24 | --hash=sha256:232ac332403e37e4a03d209a3f92ed9071f7d3dbda70e2a5e9cff1c4ba9f0678 \ 25 | --hash=sha256:23e8565ab7ff33218530bc817922fae827420f143479b753104ab801145b1d5b \ 26 | --hash=sha256:24817cb02cbef7cd499f7c9a2735286b4782bd47a5b3516a0e84c50eab44b98e \ 27 | --hash=sha256:249c6470a2b60935bafd1d1d13cd613f8cd8388d53461c67397ee6a0f5dce741 \ 28 | --hash=sha256:24a91a981f185721542a0b7c92e9054b7ab4fea0508a795846bc5b0abf8118d4 \ 29 | --hash=sha256:2502dd2a736c879c0f0d3e2161e74d9907231e25d35794584b1ca5284e43f596 \ 30 | --hash=sha256:250c9eb0f4600361dd80d46112213dff2286231d92d3e52af1e5a6083d10cad9 \ 31 | --hash=sha256:278c296c6f96fa686d74eb449ea1697f3c03dc28b75f873b65b5201806346a69 \ 32 | --hash=sha256:2935ffc78db9645cb2086c2f8f4cfd23d9b73cc0dc80334bc30aac6f03f68f8c \ 33 | --hash=sha256:2f4a0033ce9a76e391542c182f0d48d084855b5fcba5010f707c8e8c34663d77 \ 34 | --hash=sha256:30a85aed0b864ac88309b7d94be09f6046c834ef60762a8833b660139cfbad13 \ 35 | --hash=sha256:380c4bde80bce25c6e4f77b19386f5ec9db230df9f2f2ac1e5ad7af2caa70459 \ 36 | --hash=sha256:3ae38d325b512f63f8da31f826e6cb6c367336f95e418137286ba362925c877e \ 37 | --hash=sha256:3b447982ad46348c02cb90d230b75ac34e9886273df3a93eec0539308a6296d7 \ 38 | --hash=sha256:3debd1150027933210c2fc321527c2299118aa929c2f5a0a80ab6953e3bd1908 \ 39 | --hash=sha256:4162918ef3098851fcd8a628bf9b6a98d10c380725df9e04caf5ca6dd48c847a \ 40 | --hash=sha256:468d2a840567b13a590e67dd276c570f8de00ed767ecc611994c301d0f8c014f \ 41 | --hash=sha256:4cc152c5dd831641e995764f9f0b6589519f6f5123258ccaca8c6d34572fefa8 \ 42 | --hash=sha256:542da1178c1c6af8873e143910e2269add130a299c9106eef2594e15dae5e482 \ 43 | --hash=sha256:557b21a44ceac6c6b9773bc65aa1b4cc3e248a5ad2f5b914b91579a32e22204d \ 44 | --hash=sha256:5707a746c6083a3a74b46b3a631d78d129edab06195a92a8ece755aac25a3f3d \ 45 | --hash=sha256:588245972aca710b5b68802c8cad9edaa98589b1b42ad2b53accd6910dad3545 \ 46 | --hash=sha256:5adf257bd58c1b8632046bbe43ee38c04e1038e9d37de9c57a94d6bd6ce5da34 \ 47 | --hash=sha256:619d1c96099be5823db34fe89e2582b336b5b074a7f47f819d6b3a57ff7bdb86 \ 48 | --hash=sha256:63563193aec44bce707e0c5ca64ff69fa72ed7cf34ce6e11d5127555756fd2f6 \ 49 | --hash=sha256:67b8cc9574bb518ec76dc8e705d4c39ae78bb96237cb533edac149352c1f39fe \ 50 | --hash=sha256:6a685067d05e46641d5d1623d7c7fdf15a357546cbb2f71b0ebde91b175ffc3e \ 51 | --hash=sha256:70f1d09c0d7748b73290b29219e854b3207aea922f839437870d8cc2168e31cc \ 52 | --hash=sha256:750b446b2ffce1739e8578576092179160f6d26bd5e23eb1789c4d64d5af7dc7 \ 53 | --hash=sha256:7966951325782121e67c81299a031f4c115615e68046f79b85856b86ebffc4cd \ 54 | --hash=sha256:7b8b8bf1189b3ba9b8de5c8db4d541b406611a71a955bbbd7385bbc45fcb786c \ 55 | --hash=sha256:7f5d10bae5d78e4551b7be7a9b29643a95aded9d0f602aa2ba584f0388e7a557 \ 56 | --hash=sha256:805dfea4ca10411a5296bcc75638017215a93ffb584c9e344731eef0dcfb026a \ 57 | --hash=sha256:81bf654678e575403736b85ba3a7867e31c2c30a69bc57fe88e3ace52fb17b89 \ 58 | --hash=sha256:82eb849f085624f6a607538ee7b83a6d8126df6d2f7d3b319cb837b289123078 \ 59 | --hash=sha256:85a32721ddde63c9df9ebb0d2045b9691d9750cb139c161c80e500d210f5e26e \ 60 | --hash=sha256:86d1f65ac145e2c9ed71d8ffb1905e9bba3a91ae29ba55b4c46ae6fc31d7c0d4 \ 61 | --hash=sha256:86f63face3a527284f7bb8a9d4f78988e3c06823f7bea2bd6f0e0e9298ca0403 \ 62 | --hash=sha256:8eaf82f0eccd1505cf39a45a6bd0a8cf1c70dcfc30dba338207a969d91b965c0 \ 63 | --hash=sha256:93aa7eef6ee71c629b51ef873991d6911b906d7312c6e8e99790c0f33c576f89 \ 64 | --hash=sha256:96c2b49eb6a72c0e4991d62406e365d87067ca14c1a729a870d22354e6f68115 \ 65 | --hash=sha256:9cf3126b85822c4e53aa28c7ec9869b924d6fcfb76e77a45c44b83d91afd74f9 \ 66 | --hash=sha256:9fe359b2e3a7729010060fbca442ca225280c16e923b37db0e955ac2a2b72a05 \ 67 | --hash=sha256:a0ac5e7015a5920cfce654c06618ec40c33e12801711da6b4258af59a8eff00a \ 68 | --hash=sha256:a3f93dab657839dfa61025056606600a11d0b696d79386f974e459a3fbc568ec \ 69 | --hash=sha256:a4b71f4d1765639372a3b32d2638197f5cd5221b19531f9245fcc9ee62d38f56 \ 70 | --hash=sha256:aae32c93e0f64469f74ccc730a7cb21c7610af3a775157e50bbd38f816536b38 \ 71 | --hash=sha256:aaf7b34c5bc56b38c931a54f7952f1ff0ae77a2e82496583b247f7c969eb1479 \ 72 | --hash=sha256:abecce40dfebbfa6abf8e324e1860092eeca6f7375c8c4e655a8afb61af58f2c \ 73 | --hash=sha256:abf0d9f45ea5fb95051c8bfe43cb40cda383772f7e5023a83cc481ca2604d74e \ 74 | --hash=sha256:ac71b2977fb90c35d41c9453116e283fac47bb9096ad917b8819ca8b943abecd \ 75 | --hash=sha256:ada214c6fa40f8d800e575de6b91a40d0548139e5dc457d2ebb61470abf50186 \ 76 | --hash=sha256:b09719a17a2301178fac4470d54b1680b18a5048b481cb8890e1ef820cb80455 \ 77 | --hash=sha256:b1121de0e9d6e6ca08289583d7491e7fcb18a439305b34a30b20d8215922d43c \ 78 | --hash=sha256:b3b2316b25644b23b54a6f6401074cebcecd1244c0b8e80111c9a3f1c8e83d65 \ 79 | --hash=sha256:b3d9b48ee6e3967b7901c052b670c7dda6deb812c309439adaffdec55c6d7b78 \ 80 | --hash=sha256:b5bcf60a228acae568e9911f410f9d9e0d43197d030ae5799e20dca8df588287 \ 81 | --hash=sha256:b8f3307af845803fb0b060ab76cf6dd3a13adc15b6b451f54281d25911eb92df \ 82 | --hash=sha256:c2af80fb58f0f24b3f3adcb9148e6203fa67dd3f61c4af146ecad033024dde43 \ 83 | --hash=sha256:c350354efb159b8767a6244c166f66e67506e06c8924ed74669b2c70bc8735b1 \ 84 | --hash=sha256:c5a74c359b2d47d26cdbbc7845e9662d6b08a1e915eb015d044729e92e7050b7 \ 85 | --hash=sha256:c71f16da1ed8949774ef79f4a0260d28b83b3a50c6576f8f4f0288d109777989 \ 86 | --hash=sha256:d47ecf253780c90ee181d4d871cd655a789da937454045b17b5798da9393901a \ 87 | --hash=sha256:d7eff0f27edc5afa9e405f7165f85a6d782d308f3b6b9d96016c010597958e63 \ 88 | --hash=sha256:d97d85fa63f315a8bdaba2af9a6a686e0eceab77b3089af45133252618e70884 \ 89 | --hash=sha256:db756e48f9c5c607b5e33dd36b1d5872d0422e960145b08ab0ec7fd420e9d649 \ 90 | --hash=sha256:dc45229747b67ffc441b3de2f3ae5e62877a282ea828a5bdb67883c4ee4a8810 \ 91 | --hash=sha256:e0fc42822278451bc13a2e8626cf2218ba570f27856b536e00cfa53099724828 \ 92 | --hash=sha256:e39c7eb31e3f5b1f88caff88bcff1b7f8334975b46f6ac6e9fc725d829bc35d4 \ 93 | --hash=sha256:e46cd37076971c1040fc8c41273a8b3e2c624ce4f2be3f5dfcb7a430c1d3acc2 \ 94 | --hash=sha256:e5c1502d4ace69a179305abb3f0bb6141cbe4714bc9b31d427329a95acfc8bdd \ 95 | --hash=sha256:edfe077ab09442d4ef3c52cb1f9dab89bff02f4524afc0acf2d46be17dc479f5 \ 96 | --hash=sha256:effe5406c9bd748a871dbcaf3ac69167c38d72db8c9baf3ff954c344f31c4cbe \ 97 | --hash=sha256:f0d1e3732768fecb052d90d62b220af62ead5748ac51ef61e7b32c266cac9293 \ 98 | --hash=sha256:f5969baeaea61c97efa706b9b107dcba02784b1601c74ac84f2a532ea079403e \ 99 | --hash=sha256:f8888e31e3a85943743f8fc15e71536bda1c81d5aa36d014a3c0c44481d7db6e \ 100 | --hash=sha256:fc52b79d83a3fe3a360902d3f5d79073a993597d48114c29485e9431092905d8 101 | codecov==2.1.13 ; python_version >= "3.7" and python_version < "4.0" \ 102 | --hash=sha256:2362b685633caeaf45b9951a9b76ce359cd3581dd515b430c6c3f5dfb4d92a8c \ 103 | --hash=sha256:c2ca5e51bba9ebb43644c43d0690148a55086f7f5e6fd36170858fa4206744d5 104 | colorama==0.4.6 ; python_version >= "3.7" and python_version < "4.0" and sys_platform == "win32" \ 105 | --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ 106 | --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 107 | coverage==7.2.7 ; python_version >= "3.7" and python_version < "4.0" \ 108 | --hash=sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f \ 109 | --hash=sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2 \ 110 | --hash=sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a \ 111 | --hash=sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a \ 112 | --hash=sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01 \ 113 | --hash=sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6 \ 114 | --hash=sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7 \ 115 | --hash=sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f \ 116 | --hash=sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02 \ 117 | --hash=sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c \ 118 | --hash=sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063 \ 119 | --hash=sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a \ 120 | --hash=sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5 \ 121 | --hash=sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959 \ 122 | --hash=sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97 \ 123 | --hash=sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6 \ 124 | --hash=sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f \ 125 | --hash=sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9 \ 126 | --hash=sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5 \ 127 | --hash=sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f \ 128 | --hash=sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562 \ 129 | --hash=sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe \ 130 | --hash=sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9 \ 131 | --hash=sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f \ 132 | --hash=sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb \ 133 | --hash=sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb \ 134 | --hash=sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1 \ 135 | --hash=sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb \ 136 | --hash=sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250 \ 137 | --hash=sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e \ 138 | --hash=sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511 \ 139 | --hash=sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5 \ 140 | --hash=sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59 \ 141 | --hash=sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2 \ 142 | --hash=sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d \ 143 | --hash=sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3 \ 144 | --hash=sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4 \ 145 | --hash=sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de \ 146 | --hash=sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9 \ 147 | --hash=sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833 \ 148 | --hash=sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0 \ 149 | --hash=sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9 \ 150 | --hash=sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d \ 151 | --hash=sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050 \ 152 | --hash=sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d \ 153 | --hash=sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6 \ 154 | --hash=sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353 \ 155 | --hash=sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb \ 156 | --hash=sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e \ 157 | --hash=sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8 \ 158 | --hash=sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495 \ 159 | --hash=sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2 \ 160 | --hash=sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd \ 161 | --hash=sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27 \ 162 | --hash=sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1 \ 163 | --hash=sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818 \ 164 | --hash=sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4 \ 165 | --hash=sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e \ 166 | --hash=sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850 \ 167 | --hash=sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3 168 | coverage[toml]==7.2.7 ; python_version >= "3.7" and python_version < "4.0" \ 169 | --hash=sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f \ 170 | --hash=sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2 \ 171 | --hash=sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a \ 172 | --hash=sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a \ 173 | --hash=sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01 \ 174 | --hash=sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6 \ 175 | --hash=sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7 \ 176 | --hash=sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f \ 177 | --hash=sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02 \ 178 | --hash=sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c \ 179 | --hash=sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063 \ 180 | --hash=sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a \ 181 | --hash=sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5 \ 182 | --hash=sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959 \ 183 | --hash=sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97 \ 184 | --hash=sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6 \ 185 | --hash=sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f \ 186 | --hash=sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9 \ 187 | --hash=sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5 \ 188 | --hash=sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f \ 189 | --hash=sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562 \ 190 | --hash=sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe \ 191 | --hash=sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9 \ 192 | --hash=sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f \ 193 | --hash=sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb \ 194 | --hash=sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb \ 195 | --hash=sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1 \ 196 | --hash=sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb \ 197 | --hash=sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250 \ 198 | --hash=sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e \ 199 | --hash=sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511 \ 200 | --hash=sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5 \ 201 | --hash=sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59 \ 202 | --hash=sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2 \ 203 | --hash=sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d \ 204 | --hash=sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3 \ 205 | --hash=sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4 \ 206 | --hash=sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de \ 207 | --hash=sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9 \ 208 | --hash=sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833 \ 209 | --hash=sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0 \ 210 | --hash=sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9 \ 211 | --hash=sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d \ 212 | --hash=sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050 \ 213 | --hash=sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d \ 214 | --hash=sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6 \ 215 | --hash=sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353 \ 216 | --hash=sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb \ 217 | --hash=sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e \ 218 | --hash=sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8 \ 219 | --hash=sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495 \ 220 | --hash=sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2 \ 221 | --hash=sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd \ 222 | --hash=sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27 \ 223 | --hash=sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1 \ 224 | --hash=sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818 \ 225 | --hash=sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4 \ 226 | --hash=sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e \ 227 | --hash=sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850 \ 228 | --hash=sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3 229 | croniter==1.4.1 ; python_version >= "3.7" and python_version < "4.0" \ 230 | --hash=sha256:1a6df60eacec3b7a0aa52a8f2ef251ae3dd2a7c7c8b9874e73e791636d55a361 \ 231 | --hash=sha256:9595da48af37ea06ec3a9f899738f1b2c1c13da3c38cea606ef7cd03ea421128 232 | exceptiongroup==1.1.3 ; python_version >= "3.7" and python_version < "3.11" \ 233 | --hash=sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9 \ 234 | --hash=sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3 235 | fastapi==0.103.2 ; python_version >= "3.7" and python_version < "4.0" \ 236 | --hash=sha256:3270de872f0fe9ec809d4bd3d4d890c6d5cc7b9611d721d6438f9dacc8c4ef2e \ 237 | --hash=sha256:75a11f6bfb8fc4d2bec0bd710c2d5f2829659c0e8c0afd5560fdda6ce25ec653 238 | greenlet==3.0.0 ; python_version >= "3.7" and python_version < "4.0" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32") \ 239 | --hash=sha256:02a807b2a58d5cdebb07050efe3d7deaf915468d112dfcf5e426d0564aa3aa4a \ 240 | --hash=sha256:0b72b802496cccbd9b31acea72b6f87e7771ccfd7f7927437d592e5c92ed703c \ 241 | --hash=sha256:0d3f83ffb18dc57243e0151331e3c383b05e5b6c5029ac29f754745c800f8ed9 \ 242 | --hash=sha256:10b5582744abd9858947d163843d323d0b67be9432db50f8bf83031032bc218d \ 243 | --hash=sha256:123910c58234a8d40eaab595bc56a5ae49bdd90122dde5bdc012c20595a94c14 \ 244 | --hash=sha256:19834e3f91f485442adc1ee440171ec5d9a4840a1f7bd5ed97833544719ce10b \ 245 | --hash=sha256:1d363666acc21d2c204dd8705c0e0457d7b2ee7a76cb16ffc099d6799744ac99 \ 246 | --hash=sha256:211ef8d174601b80e01436f4e6905aca341b15a566f35a10dd8d1e93f5dbb3b7 \ 247 | --hash=sha256:269d06fa0f9624455ce08ae0179430eea61085e3cf6457f05982b37fd2cefe17 \ 248 | --hash=sha256:2e7dcdfad252f2ca83c685b0fa9fba00e4d8f243b73839229d56ee3d9d219314 \ 249 | --hash=sha256:334ef6ed8337bd0b58bb0ae4f7f2dcc84c9f116e474bb4ec250a8bb9bd797a66 \ 250 | --hash=sha256:343675e0da2f3c69d3fb1e894ba0a1acf58f481f3b9372ce1eb465ef93cf6fed \ 251 | --hash=sha256:37f60b3a42d8b5499be910d1267b24355c495064f271cfe74bf28b17b099133c \ 252 | --hash=sha256:38ad562a104cd41e9d4644f46ea37167b93190c6d5e4048fcc4b80d34ecb278f \ 253 | --hash=sha256:3c0d36f5adc6e6100aedbc976d7428a9f7194ea79911aa4bf471f44ee13a9464 \ 254 | --hash=sha256:3fd2b18432e7298fcbec3d39e1a0aa91ae9ea1c93356ec089421fabc3651572b \ 255 | --hash=sha256:4a1a6244ff96343e9994e37e5b4839f09a0207d35ef6134dce5c20d260d0302c \ 256 | --hash=sha256:4cd83fb8d8e17633ad534d9ac93719ef8937568d730ef07ac3a98cb520fd93e4 \ 257 | --hash=sha256:527cd90ba3d8d7ae7dceb06fda619895768a46a1b4e423bdb24c1969823b8362 \ 258 | --hash=sha256:553d6fb2324e7f4f0899e5ad2c427a4579ed4873f42124beba763f16032959af \ 259 | --hash=sha256:56867a3b3cf26dc8a0beecdb4459c59f4c47cdd5424618c08515f682e1d46692 \ 260 | --hash=sha256:621fcb346141ae08cb95424ebfc5b014361621b8132c48e538e34c3c93ac7365 \ 261 | --hash=sha256:63acdc34c9cde42a6534518e32ce55c30f932b473c62c235a466469a710bfbf9 \ 262 | --hash=sha256:6512592cc49b2c6d9b19fbaa0312124cd4c4c8a90d28473f86f92685cc5fef8e \ 263 | --hash=sha256:6672fdde0fd1a60b44fb1751a7779c6db487e42b0cc65e7caa6aa686874e79fb \ 264 | --hash=sha256:6a5b2d4cdaf1c71057ff823a19d850ed5c6c2d3686cb71f73ae4d6382aaa7a06 \ 265 | --hash=sha256:6a68d670c8f89ff65c82b936275369e532772eebc027c3be68c6b87ad05ca695 \ 266 | --hash=sha256:6bb36985f606a7c49916eff74ab99399cdfd09241c375d5a820bb855dfb4af9f \ 267 | --hash=sha256:73b2f1922a39d5d59cc0e597987300df3396b148a9bd10b76a058a2f2772fc04 \ 268 | --hash=sha256:7709fd7bb02b31908dc8fd35bfd0a29fc24681d5cc9ac1d64ad07f8d2b7db62f \ 269 | --hash=sha256:8060b32d8586e912a7b7dac2d15b28dbbd63a174ab32f5bc6d107a1c4143f40b \ 270 | --hash=sha256:80dcd3c938cbcac986c5c92779db8e8ce51a89a849c135172c88ecbdc8c056b7 \ 271 | --hash=sha256:813720bd57e193391dfe26f4871186cf460848b83df7e23e6bef698a7624b4c9 \ 272 | --hash=sha256:831d6f35037cf18ca5e80a737a27d822d87cd922521d18ed3dbc8a6967be50ce \ 273 | --hash=sha256:871b0a8835f9e9d461b7fdaa1b57e3492dd45398e87324c047469ce2fc9f516c \ 274 | --hash=sha256:952256c2bc5b4ee8df8dfc54fc4de330970bf5d79253c863fb5e6761f00dda35 \ 275 | --hash=sha256:96d9ea57292f636ec851a9bb961a5cc0f9976900e16e5d5647f19aa36ba6366b \ 276 | --hash=sha256:9a812224a5fb17a538207e8cf8e86f517df2080c8ee0f8c1ed2bdaccd18f38f4 \ 277 | --hash=sha256:9adbd8ecf097e34ada8efde9b6fec4dd2a903b1e98037adf72d12993a1c80b51 \ 278 | --hash=sha256:9de687479faec7db5b198cc365bc34addd256b0028956501f4d4d5e9ca2e240a \ 279 | --hash=sha256:a048293392d4e058298710a54dfaefcefdf49d287cd33fb1f7d63d55426e4355 \ 280 | --hash=sha256:aa15a2ec737cb609ed48902b45c5e4ff6044feb5dcdfcf6fa8482379190330d7 \ 281 | --hash=sha256:abe1ef3d780de56defd0c77c5ba95e152f4e4c4e12d7e11dd8447d338b85a625 \ 282 | --hash=sha256:ad6fb737e46b8bd63156b8f59ba6cdef46fe2b7db0c5804388a2d0519b8ddb99 \ 283 | --hash=sha256:b1660a15a446206c8545edc292ab5c48b91ff732f91b3d3b30d9a915d5ec4779 \ 284 | --hash=sha256:b505fcfc26f4148551826a96f7317e02c400665fa0883fe505d4fcaab1dabfdd \ 285 | --hash=sha256:b822fab253ac0f330ee807e7485769e3ac85d5eef827ca224feaaefa462dc0d0 \ 286 | --hash=sha256:bdd696947cd695924aecb3870660b7545a19851f93b9d327ef8236bfc49be705 \ 287 | --hash=sha256:bdfaeecf8cc705d35d8e6de324bf58427d7eafb55f67050d8f28053a3d57118c \ 288 | --hash=sha256:be557119bf467d37a8099d91fbf11b2de5eb1fd5fc5b91598407574848dc910f \ 289 | --hash=sha256:c3692ecf3fe754c8c0f2c95ff19626584459eab110eaab66413b1e7425cd84e9 \ 290 | --hash=sha256:c6b5ce7f40f0e2f8b88c28e6691ca6806814157ff05e794cdd161be928550f4c \ 291 | --hash=sha256:c94e4e924d09b5a3e37b853fe5924a95eac058cb6f6fb437ebb588b7eda79870 \ 292 | --hash=sha256:cc3e2679ea13b4de79bdc44b25a0c4fcd5e94e21b8f290791744ac42d34a0353 \ 293 | --hash=sha256:d1e22c22f7826096ad503e9bb681b05b8c1f5a8138469b255eb91f26a76634f2 \ 294 | --hash=sha256:d5539f6da3418c3dc002739cb2bb8d169056aa66e0c83f6bacae0cd3ac26b423 \ 295 | --hash=sha256:d55db1db455c59b46f794346efce896e754b8942817f46a1bada2d29446e305a \ 296 | --hash=sha256:e09dea87cc91aea5500262993cbd484b41edf8af74f976719dd83fe724644cd6 \ 297 | --hash=sha256:e52a712c38e5fb4fd68e00dc3caf00b60cb65634d50e32281a9d6431b33b4af1 \ 298 | --hash=sha256:e693e759e172fa1c2c90d35dea4acbdd1d609b6936115d3739148d5e4cd11947 \ 299 | --hash=sha256:ecf94aa539e97a8411b5ea52fc6ccd8371be9550c4041011a091eb8b3ca1d810 \ 300 | --hash=sha256:f351479a6914fd81a55c8e68963609f792d9b067fb8a60a042c585a621e0de4f \ 301 | --hash=sha256:f47932c434a3c8d3c86d865443fadc1fbf574e9b11d6650b656e602b1797908a 302 | h11==0.14.0 ; python_version >= "3.7" and python_version < "4.0" \ 303 | --hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \ 304 | --hash=sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761 305 | httpcore==0.16.3 ; python_version >= "3.7" and python_version < "4.0" \ 306 | --hash=sha256:c5d6f04e2fc530f39e0c077e6a30caa53f1451096120f1f38b954afd0b17c0cb \ 307 | --hash=sha256:da1fb708784a938aa084bde4feb8317056c55037247c787bd7e19eb2c2949dc0 308 | httpx==0.23.3 ; python_version >= "3.7" and python_version < "4.0" \ 309 | --hash=sha256:9818458eb565bb54898ccb9b8b251a28785dd4a55afbc23d0eb410754fe7d0f9 \ 310 | --hash=sha256:a211fcce9b1254ea24f0cd6af9869b3d29aba40154e947d2a07bb499b3e310d6 311 | idna==3.4 ; python_version >= "3.7" and python_version < "4.0" \ 312 | --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ 313 | --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 314 | importlib-metadata==6.7.0 ; python_version >= "3.7" and python_version < "3.8" \ 315 | --hash=sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4 \ 316 | --hash=sha256:cb52082e659e97afc5dac71e79de97d8681de3aa07ff18578330904a9d18e5b5 317 | iniconfig==2.0.0 ; python_version >= "3.7" and python_version < "4.0" \ 318 | --hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \ 319 | --hash=sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374 320 | packaging==23.2 ; python_version >= "3.7" and python_version < "4.0" \ 321 | --hash=sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5 \ 322 | --hash=sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7 323 | pluggy==1.2.0 ; python_version >= "3.7" and python_version < "4.0" \ 324 | --hash=sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849 \ 325 | --hash=sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3 326 | pydantic-core==2.10.1 ; python_version >= "3.7" and python_version < "4.0" \ 327 | --hash=sha256:042462d8d6ba707fd3ce9649e7bf268633a41018d6a998fb5fbacb7e928a183e \ 328 | --hash=sha256:0523aeb76e03f753b58be33b26540880bac5aa54422e4462404c432230543f33 \ 329 | --hash=sha256:05560ab976012bf40f25d5225a58bfa649bb897b87192a36c6fef1ab132540d7 \ 330 | --hash=sha256:0675ba5d22de54d07bccde38997e780044dcfa9a71aac9fd7d4d7a1d2e3e65f7 \ 331 | --hash=sha256:073d4a470b195d2b2245d0343569aac7e979d3a0dcce6c7d2af6d8a920ad0bea \ 332 | --hash=sha256:07ec6d7d929ae9c68f716195ce15e745b3e8fa122fc67698ac6498d802ed0fa4 \ 333 | --hash=sha256:0880e239827b4b5b3e2ce05e6b766a7414e5f5aedc4523be6b68cfbc7f61c5d0 \ 334 | --hash=sha256:0c27f38dc4fbf07b358b2bc90edf35e82d1703e22ff2efa4af4ad5de1b3833e7 \ 335 | --hash=sha256:0d8a8adef23d86d8eceed3e32e9cca8879c7481c183f84ed1a8edc7df073af94 \ 336 | --hash=sha256:0e2a35baa428181cb2270a15864ec6286822d3576f2ed0f4cd7f0c1708472aff \ 337 | --hash=sha256:0f8682dbdd2f67f8e1edddcbffcc29f60a6182b4901c367fc8c1c40d30bb0a82 \ 338 | --hash=sha256:0fa467fd300a6f046bdb248d40cd015b21b7576c168a6bb20aa22e595c8ffcdd \ 339 | --hash=sha256:128552af70a64660f21cb0eb4876cbdadf1a1f9d5de820fed6421fa8de07c893 \ 340 | --hash=sha256:1396e81b83516b9d5c9e26a924fa69164156c148c717131f54f586485ac3c15e \ 341 | --hash=sha256:149b8a07712f45b332faee1a2258d8ef1fb4a36f88c0c17cb687f205c5dc6e7d \ 342 | --hash=sha256:14ac492c686defc8e6133e3a2d9eaf5261b3df26b8ae97450c1647286750b901 \ 343 | --hash=sha256:14cfbb00959259e15d684505263d5a21732b31248a5dd4941f73a3be233865b9 \ 344 | --hash=sha256:14e09ff0b8fe6e46b93d36a878f6e4a3a98ba5303c76bb8e716f4878a3bee92c \ 345 | --hash=sha256:154ea7c52e32dce13065dbb20a4a6f0cc012b4f667ac90d648d36b12007fa9f7 \ 346 | --hash=sha256:15d6bca84ffc966cc9976b09a18cf9543ed4d4ecbd97e7086f9ce9327ea48891 \ 347 | --hash=sha256:1d40f55222b233e98e3921df7811c27567f0e1a4411b93d4c5c0f4ce131bc42f \ 348 | --hash=sha256:25bd966103890ccfa028841a8f30cebcf5875eeac8c4bde4fe221364c92f0c9a \ 349 | --hash=sha256:2cf5bb4dd67f20f3bbc1209ef572a259027c49e5ff694fa56bed62959b41e1f9 \ 350 | --hash=sha256:2e0e2959ef5d5b8dc9ef21e1a305a21a36e254e6a34432d00c72a92fdc5ecda5 \ 351 | --hash=sha256:320f14bd4542a04ab23747ff2c8a778bde727158b606e2661349557f0770711e \ 352 | --hash=sha256:3625578b6010c65964d177626fde80cf60d7f2e297d56b925cb5cdeda6e9925a \ 353 | --hash=sha256:39215d809470f4c8d1881758575b2abfb80174a9e8daf8f33b1d4379357e417c \ 354 | --hash=sha256:3f0ac9fb8608dbc6eaf17956bf623c9119b4db7dbb511650910a82e261e6600f \ 355 | --hash=sha256:417243bf599ba1f1fef2bb8c543ceb918676954734e2dcb82bf162ae9d7bd514 \ 356 | --hash=sha256:420a692b547736a8d8703c39ea935ab5d8f0d2573f8f123b0a294e49a73f214b \ 357 | --hash=sha256:443fed67d33aa85357464f297e3d26e570267d1af6fef1c21ca50921d2976302 \ 358 | --hash=sha256:48525933fea744a3e7464c19bfede85df4aba79ce90c60b94d8b6e1eddd67096 \ 359 | --hash=sha256:485a91abe3a07c3a8d1e082ba29254eea3e2bb13cbbd4351ea4e5a21912cc9b0 \ 360 | --hash=sha256:4a5be350f922430997f240d25f8219f93b0c81e15f7b30b868b2fddfc2d05f27 \ 361 | --hash=sha256:4d966c47f9dd73c2d32a809d2be529112d509321c5310ebf54076812e6ecd884 \ 362 | --hash=sha256:524ff0ca3baea164d6d93a32c58ac79eca9f6cf713586fdc0adb66a8cdeab96a \ 363 | --hash=sha256:53df009d1e1ba40f696f8995683e067e3967101d4bb4ea6f667931b7d4a01357 \ 364 | --hash=sha256:5994985da903d0b8a08e4935c46ed8daf5be1cf217489e673910951dc533d430 \ 365 | --hash=sha256:5cabb9710f09d5d2e9e2748c3e3e20d991a4c5f96ed8f1132518f54ab2967221 \ 366 | --hash=sha256:5fdb39f67c779b183b0c853cd6b45f7db84b84e0571b3ef1c89cdb1dfc367325 \ 367 | --hash=sha256:600d04a7b342363058b9190d4e929a8e2e715c5682a70cc37d5ded1e0dd370b4 \ 368 | --hash=sha256:631cb7415225954fdcc2a024119101946793e5923f6c4d73a5914d27eb3d3a05 \ 369 | --hash=sha256:63974d168b6233b4ed6a0046296803cb13c56637a7b8106564ab575926572a55 \ 370 | --hash=sha256:64322bfa13e44c6c30c518729ef08fda6026b96d5c0be724b3c4ae4da939f875 \ 371 | --hash=sha256:655f8f4c8d6a5963c9a0687793da37b9b681d9ad06f29438a3b2326d4e6b7970 \ 372 | --hash=sha256:6835451b57c1b467b95ffb03a38bb75b52fb4dc2762bb1d9dbed8de31ea7d0fc \ 373 | --hash=sha256:6db2eb9654a85ada248afa5a6db5ff1cf0f7b16043a6b070adc4a5be68c716d6 \ 374 | --hash=sha256:7c4d1894fe112b0864c1fa75dffa045720a194b227bed12f4be7f6045b25209f \ 375 | --hash=sha256:7eb037106f5c6b3b0b864ad226b0b7ab58157124161d48e4b30c4a43fef8bc4b \ 376 | --hash=sha256:8282bab177a9a3081fd3d0a0175a07a1e2bfb7fcbbd949519ea0980f8a07144d \ 377 | --hash=sha256:82f55187a5bebae7d81d35b1e9aaea5e169d44819789837cdd4720d768c55d15 \ 378 | --hash=sha256:8572cadbf4cfa95fb4187775b5ade2eaa93511f07947b38f4cd67cf10783b118 \ 379 | --hash=sha256:8cdbbd92154db2fec4ec973d45c565e767ddc20aa6dbaf50142676484cbff8ee \ 380 | --hash=sha256:8f6e6aed5818c264412ac0598b581a002a9f050cb2637a84979859e70197aa9e \ 381 | --hash=sha256:92f675fefa977625105708492850bcbc1182bfc3e997f8eecb866d1927c98ae6 \ 382 | --hash=sha256:962ed72424bf1f72334e2f1e61b68f16c0e596f024ca7ac5daf229f7c26e4208 \ 383 | --hash=sha256:9badf8d45171d92387410b04639d73811b785b5161ecadabf056ea14d62d4ede \ 384 | --hash=sha256:9c120c9ce3b163b985a3b966bb701114beb1da4b0468b9b236fc754783d85aa3 \ 385 | --hash=sha256:9f6f3e2598604956480f6c8aa24a3384dbf6509fe995d97f6ca6103bb8c2534e \ 386 | --hash=sha256:a1254357f7e4c82e77c348dabf2d55f1d14d19d91ff025004775e70a6ef40ada \ 387 | --hash=sha256:a1392e0638af203cee360495fd2cfdd6054711f2db5175b6e9c3c461b76f5175 \ 388 | --hash=sha256:a1c311fd06ab3b10805abb72109f01a134019739bd3286b8ae1bc2fc4e50c07a \ 389 | --hash=sha256:a5cb87bdc2e5f620693148b5f8f842d293cae46c5f15a1b1bf7ceeed324a740c \ 390 | --hash=sha256:a7a7902bf75779bc12ccfc508bfb7a4c47063f748ea3de87135d433a4cca7a2f \ 391 | --hash=sha256:aad7bd686363d1ce4ee930ad39f14e1673248373f4a9d74d2b9554f06199fb58 \ 392 | --hash=sha256:aafdb89fdeb5fe165043896817eccd6434aee124d5ee9b354f92cd574ba5e78f \ 393 | --hash=sha256:ae8a8843b11dc0b03b57b52793e391f0122e740de3df1474814c700d2622950a \ 394 | --hash=sha256:b00bc4619f60c853556b35f83731bd817f989cba3e97dc792bb8c97941b8053a \ 395 | --hash=sha256:b1f22a9ab44de5f082216270552aa54259db20189e68fc12484873d926426921 \ 396 | --hash=sha256:b3c01c2fb081fced3bbb3da78510693dc7121bb893a1f0f5f4b48013201f362e \ 397 | --hash=sha256:b3dcd587b69bbf54fc04ca157c2323b8911033e827fffaecf0cafa5a892a0904 \ 398 | --hash=sha256:b4a6db486ac8e99ae696e09efc8b2b9fea67b63c8f88ba7a1a16c24a057a0776 \ 399 | --hash=sha256:bec7dd208a4182e99c5b6c501ce0b1f49de2802448d4056091f8e630b28e9a52 \ 400 | --hash=sha256:c0877239307b7e69d025b73774e88e86ce82f6ba6adf98f41069d5b0b78bd1bf \ 401 | --hash=sha256:caa48fc31fc7243e50188197b5f0c4228956f97b954f76da157aae7f67269ae8 \ 402 | --hash=sha256:cfe1090245c078720d250d19cb05d67e21a9cd7c257698ef139bc41cf6c27b4f \ 403 | --hash=sha256:d43002441932f9a9ea5d6f9efaa2e21458221a3a4b417a14027a1d530201ef1b \ 404 | --hash=sha256:d64728ee14e667ba27c66314b7d880b8eeb050e58ffc5fec3b7a109f8cddbd63 \ 405 | --hash=sha256:d6495008733c7521a89422d7a68efa0a0122c99a5861f06020ef5b1f51f9ba7c \ 406 | --hash=sha256:d8f1ebca515a03e5654f88411420fea6380fc841d1bea08effb28184e3d4899f \ 407 | --hash=sha256:d99277877daf2efe074eae6338453a4ed54a2d93fb4678ddfe1209a0c93a2468 \ 408 | --hash=sha256:da01bec0a26befab4898ed83b362993c844b9a607a86add78604186297eb047e \ 409 | --hash=sha256:db9a28c063c7c00844ae42a80203eb6d2d6bbb97070cfa00194dff40e6f545ab \ 410 | --hash=sha256:dda81e5ec82485155a19d9624cfcca9be88a405e2857354e5b089c2a982144b2 \ 411 | --hash=sha256:e357571bb0efd65fd55f18db0a2fb0ed89d0bb1d41d906b138f088933ae618bb \ 412 | --hash=sha256:e544246b859f17373bed915182ab841b80849ed9cf23f1f07b73b7c58baee5fb \ 413 | --hash=sha256:e562617a45b5a9da5be4abe72b971d4f00bf8555eb29bb91ec2ef2be348cd132 \ 414 | --hash=sha256:e570ffeb2170e116a5b17e83f19911020ac79d19c96f320cbfa1fa96b470185b \ 415 | --hash=sha256:e6f31a17acede6a8cd1ae2d123ce04d8cca74056c9d456075f4f6f85de055607 \ 416 | --hash=sha256:e9121b4009339b0f751955baf4543a0bfd6bc3f8188f8056b1a25a2d45099934 \ 417 | --hash=sha256:ebedb45b9feb7258fac0a268a3f6bec0a2ea4d9558f3d6f813f02ff3a6dc6698 \ 418 | --hash=sha256:ecaac27da855b8d73f92123e5f03612b04c5632fd0a476e469dfc47cd37d6b2e \ 419 | --hash=sha256:ecdbde46235f3d560b18be0cb706c8e8ad1b965e5c13bbba7450c86064e96561 \ 420 | --hash=sha256:ed550ed05540c03f0e69e6d74ad58d026de61b9eaebebbaaf8873e585cbb18de \ 421 | --hash=sha256:eeb3d3d6b399ffe55f9a04e09e635554012f1980696d6b0aca3e6cf42a17a03b \ 422 | --hash=sha256:ef337945bbd76cce390d1b2496ccf9f90b1c1242a3a7bc242ca4a9fc5993427a \ 423 | --hash=sha256:f1365e032a477c1430cfe0cf2856679529a2331426f8081172c4a74186f1d595 \ 424 | --hash=sha256:f23b55eb5464468f9e0e9a9935ce3ed2a870608d5f534025cd5536bca25b1402 \ 425 | --hash=sha256:f2e9072d71c1f6cfc79a36d4484c82823c560e6f5599c43c1ca6b5cdbd54f881 \ 426 | --hash=sha256:f323306d0556351735b54acbf82904fe30a27b6a7147153cbe6e19aaaa2aa429 \ 427 | --hash=sha256:f36a3489d9e28fe4b67be9992a23029c3cec0babc3bd9afb39f49844a8c721c5 \ 428 | --hash=sha256:f64f82cc3443149292b32387086d02a6c7fb39b8781563e0ca7b8d7d9cf72bd7 \ 429 | --hash=sha256:f6defd966ca3b187ec6c366604e9296f585021d922e666b99c47e78738b5666c \ 430 | --hash=sha256:f7c2b8eb9fc872e68b46eeaf835e86bccc3a58ba57d0eedc109cbb14177be531 \ 431 | --hash=sha256:fa7db7558607afeccb33c0e4bf1c9a9a835e26599e76af6fe2fcea45904083a6 \ 432 | --hash=sha256:fcb83175cc4936a5425dde3356f079ae03c0802bbdf8ff82c035f8a54b333521 433 | pydantic==2.4.2 ; python_version >= "3.7" and python_version < "4.0" \ 434 | --hash=sha256:94f336138093a5d7f426aac732dcfe7ab4eb4da243c88f891d65deb4a2556ee7 \ 435 | --hash=sha256:bc3ddf669d234f4220e6e1c4d96b061abe0998185a8d7855c0126782b7abc8c1 436 | pytest-asyncio==0.21.1 ; python_version >= "3.7" and python_version < "4.0" \ 437 | --hash=sha256:40a7eae6dded22c7b604986855ea48400ab15b069ae38116e8c01238e9eeb64d \ 438 | --hash=sha256:8666c1c8ac02631d7c51ba282e0c69a8a452b211ffedf2599099845da5c5c37b 439 | pytest-cov==4.1.0 ; python_version >= "3.7" and python_version < "4.0" \ 440 | --hash=sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6 \ 441 | --hash=sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a 442 | pytest==7.4.2 ; python_version >= "3.7" and python_version < "4.0" \ 443 | --hash=sha256:1d881c6124e08ff0a1bb75ba3ec0bfd8b5354a01c194ddd5a0a870a48d99b002 \ 444 | --hash=sha256:a766259cfab564a2ad52cb1aae1b881a75c3eb7e34ca3779697c23ed47c47069 445 | python-dateutil==2.8.2 ; python_version >= "3.7" and python_version < "4.0" \ 446 | --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ 447 | --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 448 | requests==2.31.0 ; python_version >= "3.7" and python_version < "4.0" \ 449 | --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \ 450 | --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1 451 | rfc3986[idna2008]==1.5.0 ; python_version >= "3.7" and python_version < "4.0" \ 452 | --hash=sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835 \ 453 | --hash=sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97 454 | six==1.16.0 ; python_version >= "3.7" and python_version < "4.0" \ 455 | --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ 456 | --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 457 | sniffio==1.3.0 ; python_version >= "3.7" and python_version < "4.0" \ 458 | --hash=sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101 \ 459 | --hash=sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384 460 | sqlalchemy==2.0.21 ; python_version >= "3.7" and python_version < "4.0" \ 461 | --hash=sha256:014794b60d2021cc8ae0f91d4d0331fe92691ae5467a00841f7130fe877b678e \ 462 | --hash=sha256:0268256a34806e5d1c8f7ee93277d7ea8cc8ae391f487213139018b6805aeaf6 \ 463 | --hash=sha256:05b971ab1ac2994a14c56b35eaaa91f86ba080e9ad481b20d99d77f381bb6258 \ 464 | --hash=sha256:141675dae56522126986fa4ca713739d00ed3a6f08f3c2eb92c39c6dfec463ce \ 465 | --hash=sha256:1e7dc99b23e33c71d720c4ae37ebb095bebebbd31a24b7d99dfc4753d2803ede \ 466 | --hash=sha256:2e617727fe4091cedb3e4409b39368f424934c7faa78171749f704b49b4bb4ce \ 467 | --hash=sha256:3cf229704074bce31f7f47d12883afee3b0a02bb233a0ba45ddbfe542939cca4 \ 468 | --hash=sha256:3eb7c03fe1cd3255811cd4e74db1ab8dca22074d50cd8937edf4ef62d758cdf4 \ 469 | --hash=sha256:3f7d57a7e140efe69ce2d7b057c3f9a595f98d0bbdfc23fd055efdfbaa46e3a5 \ 470 | --hash=sha256:419b1276b55925b5ac9b4c7044e999f1787c69761a3c9756dec6e5c225ceca01 \ 471 | --hash=sha256:44ac5c89b6896f4740e7091f4a0ff2e62881da80c239dd9408f84f75a293dae9 \ 472 | --hash=sha256:4615623a490e46be85fbaa6335f35cf80e61df0783240afe7d4f544778c315a9 \ 473 | --hash=sha256:50a69067af86ec7f11a8e50ba85544657b1477aabf64fa447fd3736b5a0a4f67 \ 474 | --hash=sha256:513fd5b6513d37e985eb5b7ed89da5fd9e72354e3523980ef00d439bc549c9e9 \ 475 | --hash=sha256:6ff3dc2f60dbf82c9e599c2915db1526d65415be323464f84de8db3e361ba5b9 \ 476 | --hash=sha256:73c079e21d10ff2be54a4699f55865d4b275fd6c8bd5d90c5b1ef78ae0197301 \ 477 | --hash=sha256:7614f1eab4336df7dd6bee05bc974f2b02c38d3d0c78060c5faa4cd1ca2af3b8 \ 478 | --hash=sha256:785e2f2c1cb50d0a44e2cdeea5fd36b5bf2d79c481c10f3a88a8be4cfa2c4615 \ 479 | --hash=sha256:7ca38746eac23dd7c20bec9278d2058c7ad662b2f1576e4c3dbfcd7c00cc48fa \ 480 | --hash=sha256:7f0c4ee579acfe6c994637527c386d1c22eb60bc1c1d36d940d8477e482095d4 \ 481 | --hash=sha256:87bf91ebf15258c4701d71dcdd9c4ba39521fb6a37379ea68088ce8cd869b446 \ 482 | --hash=sha256:89e274604abb1a7fd5c14867a412c9d49c08ccf6ce3e1e04fffc068b5b6499d4 \ 483 | --hash=sha256:8c323813963b2503e54d0944813cd479c10c636e3ee223bcbd7bd478bf53c178 \ 484 | --hash=sha256:a95aa0672e3065d43c8aa80080cdd5cc40fe92dc873749e6c1cf23914c4b83af \ 485 | --hash=sha256:af520a730d523eab77d754f5cf44cc7dd7ad2d54907adeb3233177eeb22f271b \ 486 | --hash=sha256:b19ae41ef26c01a987e49e37c77b9ad060c59f94d3b3efdfdbf4f3daaca7b5fe \ 487 | --hash=sha256:b4eae01faee9f2b17f08885e3f047153ae0416648f8e8c8bd9bc677c5ce64be9 \ 488 | --hash=sha256:b69f1f754d92eb1cc6b50938359dead36b96a1dcf11a8670bff65fd9b21a4b09 \ 489 | --hash=sha256:b977bfce15afa53d9cf6a632482d7968477625f030d86a109f7bdfe8ce3c064a \ 490 | --hash=sha256:bf8eebccc66829010f06fbd2b80095d7872991bfe8415098b9fe47deaaa58063 \ 491 | --hash=sha256:c111cd40910ffcb615b33605fc8f8e22146aeb7933d06569ac90f219818345ef \ 492 | --hash=sha256:c2d494b6a2a2d05fb99f01b84cc9af9f5f93bf3e1e5dbdafe4bed0c2823584c1 \ 493 | --hash=sha256:c9cba4e7369de663611ce7460a34be48e999e0bbb1feb9130070f0685e9a6b66 \ 494 | --hash=sha256:cca720d05389ab1a5877ff05af96551e58ba65e8dc65582d849ac83ddde3e231 \ 495 | --hash=sha256:ccb99c3138c9bde118b51a289d90096a3791658da9aea1754667302ed6564f6e \ 496 | --hash=sha256:d59cb9e20d79686aa473e0302e4a82882d7118744d30bb1dfb62d3c47141b3ec \ 497 | --hash=sha256:e36339a68126ffb708dc6d1948161cea2a9e85d7d7b0c54f6999853d70d44430 \ 498 | --hash=sha256:ea7da25ee458d8f404b93eb073116156fd7d8c2a776d8311534851f28277b4ce \ 499 | --hash=sha256:f9fefd6298433b6e9188252f3bff53b9ff0443c8fde27298b8a2b19f6617eeb9 \ 500 | --hash=sha256:fb87f763b5d04a82ae84ccff25554ffd903baafba6698e18ebaf32561f2fe4aa \ 501 | --hash=sha256:fc6b15465fabccc94bf7e38777d665b6a4f95efd1725049d6184b3a39fd54880 502 | starlette==0.27.0 ; python_version >= "3.7" and python_version < "4.0" \ 503 | --hash=sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75 \ 504 | --hash=sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91 505 | tomli==2.0.1 ; python_version >= "3.7" and python_full_version <= "3.11.0a6" \ 506 | --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ 507 | --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f 508 | typing-extensions==4.7.1 ; python_version >= "3.7" and python_version < "4.0" \ 509 | --hash=sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36 \ 510 | --hash=sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2 511 | urllib3==2.0.6 ; python_version >= "3.7" and python_version < "4.0" \ 512 | --hash=sha256:7a7c7003b000adf9e7ca2a377c9688bbc54ed41b985789ed576570342a375cd2 \ 513 | --hash=sha256:b19e1a85d206b56d7df1d5e683df4a7725252a964e3993648dd0fb5a1c157564 514 | zipp==3.15.0 ; python_version >= "3.7" and python_version < "3.8" \ 515 | --hash=sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b \ 516 | --hash=sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556 517 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priyanshu-panwar/fastapi-utilities/733a60981f27515464f2d5c2d8ec0c6885dda0a2/tests/__init__.py -------------------------------------------------------------------------------- /tests/test_repeat_at.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import asyncio 3 | import pytest 4 | from _pytest.capture import CaptureFixture 5 | from _pytest.logging import LogCaptureFixture 6 | from fastapi_utilities import repeat_at 7 | 8 | 9 | @pytest.mark.asyncio 10 | async def test_repeat_at(capsys: CaptureFixture[str]): 11 | """ 12 | Simple Test Case for repeat_at 13 | """ 14 | 15 | @repeat_at(cron="* * * * *", max_repetitions=3) 16 | async def print_hello(): 17 | print("Hello") 18 | 19 | asyncio.create_task(print_hello()) 20 | await asyncio.sleep(1) 21 | out, err = capsys.readouterr() 22 | assert err == "" 23 | assert out == "" 24 | 25 | 26 | @pytest.mark.asyncio 27 | async def test_repeat_at_def(capsys: CaptureFixture[str]): 28 | """ 29 | Simple Test Case for repeat_at 30 | """ 31 | 32 | @repeat_at(cron="* * * * *", max_repetitions=3) 33 | def print_hello(): 34 | print("Hello") 35 | 36 | print_hello() 37 | await asyncio.sleep(1) 38 | out, err = capsys.readouterr() 39 | assert err == "" 40 | assert out == "" 41 | 42 | 43 | @pytest.mark.asyncio 44 | async def test_repeat_at_with_logger(caplog: LogCaptureFixture): 45 | """ 46 | Test Case for repeat_at with logger 47 | """ 48 | 49 | @repeat_at(cron="* * * * *", logger=logging.getLogger("test"), max_repetitions=3) 50 | async def print_hello(): 51 | raise Exception("Hello") 52 | 53 | asyncio.create_task(print_hello()) 54 | await asyncio.sleep(60) 55 | 56 | captured_logs = caplog.records 57 | 58 | assert len(captured_logs) > 0 59 | 60 | 61 | from asyncio import AbstractEventLoop 62 | from typing import Any, Dict 63 | 64 | 65 | def ignore_exception(_loop: AbstractEventLoop, _context: Dict[str, Any]) -> None: 66 | pass 67 | 68 | 69 | @pytest.fixture(autouse=True) 70 | def setup_event_loop(event_loop: AbstractEventLoop) -> None: 71 | event_loop.set_exception_handler(ignore_exception) 72 | 73 | 74 | @pytest.mark.asyncio 75 | async def test_repeat_at_exception(capsys: CaptureFixture[str]) -> None: 76 | """ 77 | Test Case for repeat_at with an invalid cron expression 78 | """ 79 | 80 | logger = logging.getLogger(__name__) 81 | 82 | @repeat_at( 83 | cron="* * * * *", max_repetitions=None, raise_exceptions=True, logger=logger 84 | ) 85 | def raise_exc(): 86 | raise ValueError("repeat") 87 | 88 | try: 89 | raise_exc() 90 | await asyncio.sleep(60) 91 | except ValueError: 92 | out, err = capsys.readouterr() 93 | assert out == "" 94 | assert err == "" 95 | 96 | 97 | @pytest.mark.asyncio 98 | async def test_repeat_at_invalid_cron(capsys: CaptureFixture[str]) -> None: 99 | """ 100 | Test Case for repeat_at with an invalid cron expression 101 | """ 102 | 103 | logger = logging.getLogger(__name__) 104 | 105 | @repeat_at( 106 | cron="invalid", max_repetitions=None, raise_exceptions=True, logger=logger 107 | ) 108 | def raise_exc(): 109 | raise ValueError("repeat") 110 | 111 | try: 112 | await raise_exc() 113 | await asyncio.sleep(60) 114 | except ValueError: 115 | out, err = capsys.readouterr() 116 | assert out == "" 117 | assert err == "" 118 | -------------------------------------------------------------------------------- /tests/test_repeat_every.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import pytest 3 | import asyncio 4 | 5 | from _pytest.capture import CaptureFixture 6 | from _pytest.logging import LogCaptureFixture 7 | from fastapi_utilities import repeat_every 8 | 9 | 10 | @pytest.mark.asyncio 11 | async def test_repeat_every(capsys: CaptureFixture[str]): 12 | """ 13 | Simple Test Case for repeat_every 14 | """ 15 | 16 | @repeat_every(seconds=0.1, max_repetitions=3) 17 | async def print_hello(): 18 | print("Hello") 19 | 20 | await print_hello() 21 | await asyncio.sleep(0.5) 22 | out, err = capsys.readouterr() 23 | assert out == "Hello\nHello\nHello\n" 24 | assert err == "" 25 | 26 | 27 | @pytest.mark.asyncio 28 | async def test_repeat_every_sync(capsys: CaptureFixture[str]): 29 | """ 30 | Simple Test Case for repeat_every 31 | """ 32 | 33 | @repeat_every(seconds=0.1, max_repetitions=3) 34 | def print_hello(): 35 | print("Hello") 36 | 37 | await print_hello() 38 | await asyncio.sleep(0.5) 39 | out, err = capsys.readouterr() 40 | assert out == "Hello\nHello\nHello\n" 41 | assert err == "" 42 | 43 | 44 | @pytest.mark.asyncio 45 | async def test_repeat_every_with_wait_first(capsys: CaptureFixture[str]): 46 | """ 47 | Test Case for repeat_every with wait_first=True 48 | """ 49 | 50 | @repeat_every(seconds=0.1, wait_first=True, max_repetitions=3) 51 | async def print_hello(): 52 | print("Hello") 53 | 54 | await print_hello() 55 | await asyncio.sleep(0.5) 56 | out, err = capsys.readouterr() 57 | assert out == "Hello\nHello\nHello\n" 58 | assert err == "" 59 | 60 | 61 | @pytest.mark.asyncio 62 | async def test_repeat_every_with_logger(caplog: LogCaptureFixture): 63 | """ 64 | Test Case for repeat_every with logger 65 | """ 66 | 67 | @repeat_every(seconds=0.1, logger=logging.getLogger("test"), max_repetitions=3) 68 | async def print_hello(): 69 | raise Exception("Hello") 70 | 71 | await print_hello() 72 | await asyncio.sleep(0.5) 73 | 74 | captured_logs = caplog.records 75 | 76 | assert len(captured_logs) > 0 77 | 78 | last_log = captured_logs[-1] # Get the last log message 79 | assert last_log.levelname == "ERROR" # Check log level 80 | assert "Hello" in last_log.message # Check log message content 81 | 82 | 83 | from asyncio import AbstractEventLoop 84 | from typing import Any, Dict 85 | 86 | 87 | def ignore_exception(_loop: AbstractEventLoop, _context: Dict[str, Any]) -> None: 88 | pass 89 | 90 | 91 | @pytest.fixture(autouse=True) 92 | def setup_event_loop(event_loop: AbstractEventLoop) -> None: 93 | event_loop.set_exception_handler(ignore_exception) 94 | 95 | 96 | @pytest.mark.asyncio 97 | async def test_repeat_raise_error(capsys: CaptureFixture[str]) -> None: 98 | logger = logging.getLogger(__name__) 99 | 100 | @repeat_every( 101 | seconds=0.07, max_repetitions=None, raise_exceptions=True, logger=logger 102 | ) 103 | def raise_exc(): 104 | raise ValueError("repeat") 105 | 106 | await raise_exc() 107 | await asyncio.sleep(0.1) 108 | out, err = capsys.readouterr() 109 | assert out == "" 110 | assert err == "" 111 | -------------------------------------------------------------------------------- /tests/test_session.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from pathlib import Path 3 | import random 4 | from _pytest.capture import CaptureFixture 5 | 6 | from fastapi import FastAPI 7 | from fastapi.testclient import TestClient 8 | from fastapi_utilities import FastAPISessionMaker 9 | 10 | # setup 11 | db_path = Path("./db.sqlite3") 12 | 13 | from sqlalchemy import create_engine 14 | from sqlalchemy.orm import sessionmaker, declarative_base 15 | 16 | DB_URL = f"sqlite:///{db_path}" 17 | engine = create_engine(DB_URL, connect_args={"check_same_thread": False}) 18 | Base = declarative_base() 19 | 20 | SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) 21 | 22 | from sqlalchemy import Column, Integer 23 | 24 | 25 | class User(Base): 26 | __tablename__ = "users" 27 | 28 | id = Column(Integer, primary_key=True) 29 | 30 | 31 | app = FastAPI() 32 | Base.metadata.create_all(bind=engine) 33 | 34 | # done 35 | 36 | 37 | def test_session(): 38 | sm = FastAPISessionMaker(DB_URL) 39 | with sm.context_session() as session: 40 | x = User(id=random.randint(0, 10000)) 41 | session.add(x) 42 | 43 | 44 | def test_reset_session(): 45 | sm = FastAPISessionMaker(DB_URL) 46 | sm.reset_session() 47 | 48 | 49 | def test_session_raise_error(capsys: CaptureFixture[str]) -> None: 50 | sm = FastAPISessionMaker(DB_URL) 51 | try: 52 | with sm.context_session() as session: 53 | x = User(id=1) 54 | session.add(x) 55 | x = User(id=1) 56 | session.add(x) 57 | except Exception: 58 | out, err = capsys.readouterr() 59 | assert out == "" 60 | -------------------------------------------------------------------------------- /tests/test_timer_middleware.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import pytest 3 | import asyncio 4 | from fastapi import FastAPI 5 | from fastapi.testclient import TestClient 6 | from _pytest.capture import CaptureFixture 7 | from fastapi_utilities import add_timer_middleware 8 | 9 | app = FastAPI() 10 | add_timer_middleware(app, show_avg=True, reset_after=1) 11 | 12 | 13 | @app.get("/") 14 | def root(): 15 | pass 16 | 17 | 18 | client = TestClient(app) 19 | 20 | 21 | def test_timer_middleware(capsys: CaptureFixture[str]) -> None: 22 | client.get("/") 23 | out, err = capsys.readouterr() 24 | assert err == "" 25 | --------------------------------------------------------------------------------