From ec5c5c793a8a17aebcc36a21a3479e018c20777c Mon Sep 17 00:00:00 2001 From: Aleksandr Osovskii Date: Wed, 14 May 2025 14:35:55 +0300 Subject: [PATCH 01/18] fix: documentation link fix --- README.md | 190 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 142 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index c838f31a..7bfc0c0a 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,11 @@ *Библиотека для создания чат-ботов и SmartApps для мессенджера eXpress* -[![PyPI version](https://badge.fury.io/py/botx.svg)](https://badge.fury.io/py/pybotx) +[![PyPI version](https://badge.fury.io/py/pybotx.svg)](https://badge.fury.io/py/pybotx) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pybotx) [![Coverage](https://codecov.io/gh/ExpressApp/pybotx/branch/master/graph/badge.svg)](https://codecov.io/gh/ExpressApp/pybotx/branch/master) [![Code style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black) - ## Особенности * Простая для использования @@ -16,7 +15,6 @@ * Полное покрытие тестами * Полное покрытие аннотациями типов - ## Установка Используя `poetry`: @@ -28,24 +26,22 @@ poetry add pybotx **Предупреждение:** Данный проект находится в активной разработке (`0.y.z`) и его API может быть изменён при повышении минорной версии. - ## Информация о мессенджере eXpress и платформе BotX -Документацию по мессенджеру (включая руководство пользователя и администратора) -можно найти на [официальном сайте](https://express.ms/). +[Документация](https://docs.express.ms/) по мессенджеру (включая руководство пользователя и администратора). Перед тем, как продолжать знакомство с библиотекой `pybotx`, -советуем прочитать данные статьи: [Что такое чат-боты и SmartApp -](https://ccsteam.atlassian.net/wiki/spaces/SMARTAPP/pages/311001089) -и [Взаимодействие с Bot API и BotX API -](https://ccsteam.atlassian.net/wiki/spaces/SMARTAPP/pages/311001185). +советуем прочитать данные +статьи: Что +такое [чат-боты](https://docs.express.ms/chatbots/developer-guide/#%D1%87%D0%B0%D1%82-%D0%B1%D0%BE%D1%82-%D0%B8-smartapp) +и [SmartApp](https://docs.express.ms/smartapps/developer-guide/) +и [Взаимодействие с Bot API и BotX API](https://docs.express.ms/chatbots/developer-guide/api/). В этих статьях находятся исчерпывающие примеры работы с платформой, которые легко повторить, используя `pybotx`. Также не будет лишним ознакомиться с [документацией по плаформе BotX ](https://hackmd.ccsteam.ru/s/botx_platform). - ## Примеры готовых проектов на базе pybotx * [Next Feature Bot](https://github.com/ExpressApp/next-feature-bot) - бот, @@ -55,7 +51,6 @@ poetry add pybotx * [Weather SmartApp](https://github.com/ExpressApp/weather-smartapp) - приложение для просмотра погоды. - ## Минимальный пример бота (интеграция с FastAPI) ```python @@ -88,7 +83,7 @@ bot = Bot( # Не забудьте заменить эти учётные данные на настоящие, # когда создадите бота в панели администратора. id=UUID("123e4567-e89b-12d3-a456-426655440000"), - host="cts.example.com", + cts_url="https://cts.example.com", secret_key="e29b417773f2feab9dac143ee3da20c5", ), ], @@ -103,18 +98,34 @@ app.add_event_handler("shutdown", bot.shutdown) # (сообщения и системные события). @app.post("/command") async def command_handler(request: Request) -> JSONResponse: - bot.async_execute_raw_bot_command(await request.json()) + bot.async_execute_raw_bot_command( + await request.json(), + request_headers=request.headers, + ) return JSONResponse( build_command_accepted_response(), status_code=HTTPStatus.ACCEPTED, ) +# На этот эндпоинт приходят события BotX для SmartApps, обрабатываемые синхронно. +@app.post("/smartapps/request") +async def sync_smartapp_event_handler(request: Request) -> JSONResponse: + response = await bot.sync_execute_raw_smartapp_event( + await request.json(), + request_headers=request.headers, + ) + return JSONResponse(response.jsonable_dict(), status_code=HTTPStatus.OK) + + # К этому эндпоинту BotX обращается, чтобы узнать # доступность бота и его список команд. @app.get("/status") async def status_handler(request: Request) -> JSONResponse: - status = await bot.raw_get_status(dict(request.query_params)) + status = await bot.raw_get_status( + dict(request.query_params), + request_headers=request.headers, + ) return JSONResponse(status) @@ -122,7 +133,10 @@ async def status_handler(request: Request) -> JSONResponse: # выполнения асинхронных методов в BotX. @app.post("/notification/callback") async def callback_handler(request: Request) -> JSONResponse: - await bot.set_raw_botx_method_result(await request.json()) + await bot.set_raw_botx_method_result( + await request.json(), + verify_request=False, + ) return JSONResponse( build_command_accepted_response(), status_code=HTTPStatus.ACCEPTED, @@ -131,11 +145,10 @@ async def callback_handler(request: Request) -> JSONResponse: ## Примеры - ### Получение сообщений *([подробное описание функции]( -https://ccsteam.atlassian.net/wiki/spaces/SMARTAPP/pages/311001185/Bot+API+BotX+API#%D0%9F%D0%BE%D0%BB%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B9/%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%BD%D1%8B%D1%85-%D1%81%D0%BE%D0%B1%D1%8B%D1%82%D0%B8%D0%B9))* +https://docs.express.ms/chatbots/developer-guide/api/bot-api/command/))* ```python from uuid import UUID @@ -179,11 +192,10 @@ async def default_handler(_: IncomingMessage, bot: Bot) -> None: print("Hello from default handler") ``` - ### Получение системных событий *([подробное описание функции]( -https://ccsteam.atlassian.net/wiki/spaces/SMARTAPP/pages/311001185/Bot+API+BotX+API#%D0%9F%D0%BE%D0%BB%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B9/%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%BD%D1%8B%D1%85-%D1%81%D0%BE%D0%B1%D1%8B%D1%82%D0%B8%D0%B9))* +https://docs.express.ms/chatbots/developer-guide/api/bot-api/command/#%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%BD%D1%8B%D0%B5-%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D1%8B))* ```python from pybotx import * @@ -203,6 +215,25 @@ async def smartapp_event_handler(event: SmartAppEvent, bot: Bot) -> None: print(f"Got `smartapp_event` event: {event}") ``` +### Получение синхронных SmartApp событий + +```python +from pybotx import * + +collector = HandlerCollector() + + +# Обработчик синхронных Smartapp событий, приходящих на эндпоинт `/smartapps/request` +@collector.sync_smartapp_event +async def handle_sync_smartapp_event( + event: SmartAppEvent, bot: Bot, +) -> BotAPISyncSmartAppEventResultResponse: + print(f"Got sync smartapp event: {event}") + return BotAPISyncSmartAppEventResultResponse.from_domain( + data={}, + files=[], + ) +``` ### Middlewares @@ -217,9 +248,9 @@ collector = HandlerCollector() async def custom_api_client_middleware( - message: IncomingMessage, - bot: Bot, - call_next: IncomingMessageHandlerFunc, + message: IncomingMessage, + bot: Bot, + call_next: IncomingMessageHandlerFunc, ) -> None: # До вызова `call_next` (обязателен в каждой миддлвари) располагается # код, который выполняется до того, как сообщение дойдёт до @@ -261,18 +292,18 @@ ADMIN_HUIDS = (UUID("123e4567-e89b-12d3-a456-426614174000"),) async def request_id_middleware( - message: IncomingMessage, - bot: Bot, - call_next: IncomingMessageHandlerFunc, + message: IncomingMessage, + bot: Bot, + call_next: IncomingMessageHandlerFunc, ) -> None: message.state.request_id = uuid4() await call_next(message, bot) async def ensure_admin_middleware( - message: IncomingMessage, - bot: Bot, - call_next: IncomingMessageHandlerFunc, + message: IncomingMessage, + bot: Bot, + call_next: IncomingMessageHandlerFunc, ) -> None: if message.sender.huid not in ADMIN_HUIDS: await bot.answer_message("You are not admin") @@ -296,11 +327,10 @@ admin_collector = HandlerCollector(middlewares=[ensure_admin_middleware]) main_collector.include(admin_collector) ``` - ### Отправка сообщения *([подробное описание функции]( -https://ccsteam.atlassian.net/wiki/spaces/SMARTAPP/pages/311001185/Bot+API+BotX+API#%D0%9E%D1%82%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B0-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D1%8F))* +https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D0%BE%D1%82%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B0-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D1%8F))* ```python from uuid import UUID @@ -352,11 +382,10 @@ async def prebuild_answer_handler(message: IncomingMessage, bot: Bot) -> None: await bot.send(message=answer) ``` - #### Отправка сообщения с кнопками *([подробное описание функции]( -https://ccsteam.atlassian.net/wiki/spaces/SMARTAPP/pages/311001185/Bot+API+BotX+API#%D0%9E%D1%82%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B0-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D1%8F-%D1%81-%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D0%B0%D0%BC%D0%B8))* +https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D0%BE%D1%82%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B0-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D1%8F-%D1%81-%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D0%B0%D0%BC%D0%B8))* ```python from pybotx import * @@ -374,25 +403,35 @@ async def bubbles_handler(message: IncomingMessage, bot: Bot) -> None: command="/choose", label="Red", data={"pill": "red"}, + background_color="#FF0000", ) bubbles.add_button( command="/choose", label="Blue", data={"pill": "blue"}, + background_color="#0000FF", new_row=False, ) + # В кнопку можно добавит ссылку на ресурс, + # для этого нужно добавить url в аргумент `link`, а `command` оставить пустым, + # `alert` добавляется в окно подтверждения при переходе по ссылке. + bubbles.add_button( + label="Bubble with link", + alert="alert text", + link="https://example.com", + ) + await bot.answer_message( "The time has come to make a choice, Mr. Anderson:", bubbles=bubbles, ) ``` - #### Упоминание пользователя *([подробное описание функции]( -https://ccsteam.atlassian.net/wiki/spaces/SMARTAPP/pages/311001185/Bot+API+BotX+API#%D0%A3%D0%BF%D0%BE%D0%BC%D0%B8%D0%BD%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8F))* +https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D1%83%D0%BF%D0%BE%D0%BC%D0%B8%D0%BD%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8F))* ```python from pybotx import * @@ -416,11 +455,10 @@ async def echo_contact_handler(message: IncomingMessage, bot: Bot) -> None: await bot.answer_message(answer) ``` - #### Отправка файла в сообщении *([подробное описание функции]( -https://ccsteam.atlassian.net/wiki/spaces/SMARTAPP/pages/311001185/Bot+API+BotX+API#%D0%9E%D1%82%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B0-%D1%84%D0%B0%D0%B9%D0%BB%D0%B0-%D0%B2-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B8))* +https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D0%BE%D1%82%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B0-%D1%84%D0%B0%D0%B9%D0%BB%D0%B0-%D0%B2-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B8))* ```python from aiofiles.tempfile import NamedTemporaryFile @@ -452,11 +490,10 @@ async def echo_file_handler(message: IncomingMessage, bot: Bot) -> None: await bot.answer_message("", file=attached_file) ``` - ### Редактирование сообщения *([подробное описание функции]( -https://hackmd.ccsteam.ru/s/E9MPeOxjP#%D0%A0%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D1%81%D0%BE%D0%B1%D1%8B%D1%82%D0%B8%D1%8F))* +https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D1%80%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B9))* ```python from pybotx import * @@ -492,6 +529,34 @@ async def increment_handler(message: IncomingMessage, bot: Bot) -> None: await bot.answer_message(answer_text, bubbles=bubbles) ``` +### Удаление сообщения + +*([подробное описание функции]( +https://hackmd.ccsteam.ru/s/E9MPeOxjP#%D0%A3%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D1%8F))* + +```python +from pybotx import * + +collector = HandlerCollector() + + +@collector.command("/deleted-message", description="Self-deleted message") +async def deleted_message_handler(message: IncomingMessage, bot: Bot) -> None: + if message.source_sync_id: # ID сообщения, в котором была нажата кнопка. + await bot.delete_message( + bot_id=message.bot.id, + sync_id=message.source_sync_id, + ) + return + + bubbles = BubbleMarkup() + bubbles.add_button( + command="/deleted-message", + label="Delete", + ) + + await bot.answer_message("Self-deleted message", bubbles=bubbles) +``` ### Обработчики ошибок @@ -504,9 +569,9 @@ from pybotx import * async def internal_error_handler( - message: IncomingMessage, - bot: Bot, - exc: Exception, + message: IncomingMessage, + bot: Bot, + exc: Exception, ) -> None: logger.exception("Internal error:") @@ -527,7 +592,7 @@ bot = Bot( ### Создание чата *([подробное описание функции]( -https://ccsteam.atlassian.net/wiki/spaces/SMARTAPP/pages/311001185/Bot+API+BotX+API#%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5-%D1%87%D0%B0%D1%82%D0%B0))* +https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5-%D1%87%D0%B0%D1%82%D0%B0))* ```python from pybotx import * @@ -556,8 +621,37 @@ async def create_group_chat_handler(message: IncomingMessage, bot: Bot) -> None: await bot.answer_message(f"Chat created: {chat_mention}") ``` +### Поиск пользователей + +*([подробное описание функции]( +https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D0%BF%D0%BE%D0%B8%D1%81%D0%BA-%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8F))* + +```python +import dataclasses + +from pybotx import * + +collector = HandlerCollector() + + +@collector.command("/my-info", description="Get info of current user") +async def search_user_handler(message: IncomingMessage, bot: Bot) -> None: + try: + user_info = await bot.search_user_by_huid( + bot_id=message.bot.id, + huid=message.sender.huid, + ) + except UserNotFoundError: # Если пользователь и бот находятся на разных CTS + await bot.answer_message("User not found. Maybe you are on a different cts.") + return + + await bot.answer_message(f"Your info:\n{dataclasses.asdict(user_info)}\n") +``` + ### Получение списка пользователей -*([подробное описание функции](https://ccsteam.atlassian.net/wiki/spaces/SMARTAPP/pages/311001185/Bot+API+BotX+API#%D0%9F%D0%BE%D0%BB%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D0%BF%D0%B8%D1%81%D0%BA%D0%B0-%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B5%D0%B9-%D0%BD%D0%B0-CTS))* + +*([подробное описание функции]( +https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D0%BF%D0%BE%D0%BB%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D0%BF%D0%B8%D1%81%D0%BA%D0%B0-%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B5%D0%B9-%D0%BD%D0%B0-cts))* ```python from pybotx import * @@ -568,10 +662,10 @@ collector = HandlerCollector() @collector.command("/get_users_list", description="Get a list of users") async def users_list_handler(message: IncomingMessage, bot: Bot) -> None: async with bot.users_as_csv( - bot_id=message.bot.id, - cts_user=True, - unregistered=False, - botx=False, + bot_id=message.bot.id, + cts_user=True, + unregistered=False, + botx=False, ) as users: async for user in users: print(user) From 110b2bf417f19bf7ee8043bfb225d9f51104af46 Mon Sep 17 00:00:00 2001 From: Aleksandr Osovskii Date: Wed, 14 May 2025 14:40:09 +0300 Subject: [PATCH 02/18] feat: dropped support for Python 3.8 and bump libs --- .github/workflows/python-app.yml | 15 +- poetry.lock | 1132 +++++++++++++++++------------- pyproject.toml | 27 +- 3 files changed, 650 insertions(+), 524 deletions(-) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 8fb1a8a6..f4f88195 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -4,14 +4,14 @@ jobs: test: name: Test - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11"] + python-version: ["3.9", "3.10", "3.11", "3.12"] steps: - name: Setup dependencies - uses: ExpressApp/github-actions-poetry@v0.3 + uses: ExpressApp/github-actions-poetry@v0.4 with: python-version: ${{ matrix.python-version }} poetry-version: "1.3.2" @@ -28,14 +28,15 @@ jobs: fail_ci_if_error: true files: ./coverage.xml flags: unittests + token: ${{ secrets.CODECOV_TOKEN }} lint: name: Lint - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Setup dependencies - uses: ExpressApp/github-actions-poetry@v0.3 + uses: ExpressApp/github-actions-poetry@v0.4 with: python-version: ${{ matrix.python-version }} poetry-version: "1.3.2" @@ -46,11 +47,11 @@ jobs: docs-lint: name: Docs lint - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Setup dependencies - uses: ExpressApp/github-actions-poetry@v0.3 + uses: ExpressApp/github-actions-poetry@v0.4 with: python-version: ${{ matrix.python-version }} poetry-version: "1.3.2" diff --git a/poetry.lock b/poetry.lock index 59bfedc9..3ac3d5c2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,12 +1,12 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand. [[package]] name = "add-trailing-comma" version = "2.2.1" description = "Automatically add trailing commas to calls and literals" -category = "dev" optional = false python-versions = ">=3.6.1" +groups = ["dev"] files = [ {file = "add_trailing_comma-2.2.1-py2.py3-none-any.whl", hash = "sha256:981c18282b38ec5bceab80ef11485440334d2a274fcf3fce1f91692374b6d818"}, {file = "add_trailing_comma-2.2.1.tar.gz", hash = "sha256:1640e97c4e85132633a6cb19b29e392dbaf9516292388afa685f7ef1012468e0"}, @@ -17,83 +17,84 @@ tokenize-rt = ">=3.0.1" [[package]] name = "aiocsv" -version = "1.2.4" +version = "1.2.5" description = "Asynchronous CSV reading/writing" -category = "main" optional = false python-versions = ">=3.6, <4" -files = [ - {file = "aiocsv-1.2.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6143d3c1f9535b3bb64ab5a3426ca49419ef193b987dbbb15737d5972cc7b196"}, - {file = "aiocsv-1.2.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bbb0e2cbc3cf8c3f24da8fb0a9b3c697d98db1d63fffaa68b442fae0346a8ee"}, - {file = "aiocsv-1.2.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8c2e8705d2717b81a6cb86c767941f2511d4c1751b4f1a58f3b24a705b720c66"}, - {file = "aiocsv-1.2.4-cp310-cp310-win_amd64.whl", hash = "sha256:4479fda6cd395008a22b3c04e8e960c110455324c2c2fc27157e9569698bc224"}, - {file = "aiocsv-1.2.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:59ddcacdcf4d57e667dc75b3a0354ab0b1f5eabe9088a7e5fccab96dd400ef61"}, - {file = "aiocsv-1.2.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e32053cb29d28ce7c1b539bb040aafd5bee3934d409045f87de072baa4488e4"}, - {file = "aiocsv-1.2.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ee0b79ed8b8a3f11ec28ca61cb9074f40f4180b25f47a63074e81b93d0fe751a"}, - {file = "aiocsv-1.2.4-cp311-cp311-win_amd64.whl", hash = "sha256:0184c46515957788bec90e4661b3e741209ba9e7c8c0db2b26019426d0ff6221"}, - {file = "aiocsv-1.2.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:3a8956d0a60de25d4701e680ff9783eeb89721fec9ad26f3c764686e2b6d074e"}, - {file = "aiocsv-1.2.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d865c4d3abf21c590c25c531f367aa61f1c20f520ec05eec1d8e5ee1c8393316"}, - {file = "aiocsv-1.2.4-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e717f15cca53b1288d5b6689cff4b798c848b40ba99a5def10d4694223530daf"}, - {file = "aiocsv-1.2.4-cp36-cp36m-win_amd64.whl", hash = "sha256:b47dfc3ea2baee21baefa875188c6b65ae64fd84831fc796a049f88e91245f9a"}, - {file = "aiocsv-1.2.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:239a5cd94c0936774b087c266dfb6688b93bc50839652f5b9dba94bd039cac57"}, - {file = "aiocsv-1.2.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f490c9a9862888e934beb91492ebac8024fe43871a19eb17c64a952128525eb3"}, - {file = "aiocsv-1.2.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c6f9170a0235e770d6cd7acacd084ba6b7fc06a2ee9a5a8f18b445d5c2081618"}, - {file = "aiocsv-1.2.4-cp37-cp37m-win_amd64.whl", hash = "sha256:c5ae550d35e65c965ffe90d7bebe802a3ab75ab7b7b1aac73dd3a26b5e46fa83"}, - {file = "aiocsv-1.2.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:264e35c09c0dd735b41e43c2cccc05d19fc685b0ef828c5da56e2800e0ffefd9"}, - {file = "aiocsv-1.2.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82dfe16bd19dcfbbafeffb68a0e67577192c49ffe2e2d678f476fc761fcb7ded"}, - {file = "aiocsv-1.2.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3892ddcae649fa6dfa7dc2ced97131c6f2444b60fee97dd944cf9d43d1b51aa2"}, - {file = "aiocsv-1.2.4-cp38-cp38-win_amd64.whl", hash = "sha256:4246180c5c9980f25c07627bf7f928ec7d58e0f119c9904add69b8f264763fcd"}, - {file = "aiocsv-1.2.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5554f0ad0725b44682b714f3cd039b092af1ca9219e20fc029b8c3db7c928ce6"}, - {file = "aiocsv-1.2.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02bd8f1ec4676894194043461c55d371b906ab9f16dd460606dccda74850de37"}, - {file = "aiocsv-1.2.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e088937657a99bcd346a22bc0948b29d4ffa1d60976dc1a37d4df8104a08f2ab"}, - {file = "aiocsv-1.2.4-cp39-cp39-win_amd64.whl", hash = "sha256:d33222cef014d396400b26011c3456cc1abaf1b2ca344c2945969fbd48c5f9e8"}, - {file = "aiocsv-1.2.4.tar.gz", hash = "sha256:f592cb62ef52471ca42a762e89d0a02fcde395067041a7d70972aefa722c0fcd"}, +groups = ["main"] +files = [ + {file = "aiocsv-1.2.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a8221a24220c3dfed5df80c87bb1e15d4863816954b5f1fca1dcfc14328c0131"}, + {file = "aiocsv-1.2.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:274df72bc8d0d11060c148523203f93cfa830dc9901a053d27032e4be0acb50e"}, + {file = "aiocsv-1.2.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c99bc418c869e23bbae52dc7c9f05c97b351460c848cb033d7b09b472d8d3e46"}, + {file = "aiocsv-1.2.5-cp310-cp310-win_amd64.whl", hash = "sha256:f78600e29e9dd7c35711bc1a07176fc76921fc42a65da0135e1c213abb5dc6d5"}, + {file = "aiocsv-1.2.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a499b9b2edf618142e107a54f91536e9b9457f182d721e993c9ed14a8c7353b5"}, + {file = "aiocsv-1.2.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4681ae9b7f57423fa09718369e5ecd234889c58ba4f4c203f825e682afc240a"}, + {file = "aiocsv-1.2.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ceff6f3ea9e09b7c48736823261de7b5e7b9b9daec18862c25033ed5ef426590"}, + {file = "aiocsv-1.2.5-cp311-cp311-win_amd64.whl", hash = "sha256:7064193c3d3145d763315118df1abe93a57c2b879ab62c73fc6da77009652e50"}, + {file = "aiocsv-1.2.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f1768d44e15ab2f8789e1fd0fbe2feaf9168642cf65fcf760bf61fbc1a100ada"}, + {file = "aiocsv-1.2.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:733c820e8138b96b6110a44f7eebe3e4e9d9e1261ed67c6a93e8b964807c4346"}, + {file = "aiocsv-1.2.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:030d8f1bc33b7746ced9ff328ce881406e1c78a52f83ad26832c220d2dec8777"}, + {file = "aiocsv-1.2.5-cp36-cp36m-win_amd64.whl", hash = "sha256:790393c322db1be0353045b2db255e3147a0cab1ee78ecc1b14a1df7d8651460"}, + {file = "aiocsv-1.2.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a23c450fe3f6f3b96b826348a4b30cd884edfdc46a3c11ac30802e720cabafc2"}, + {file = "aiocsv-1.2.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1663f81741a2660d0669acb71e2f8c820c997f8761531018800d74cc669889a"}, + {file = "aiocsv-1.2.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:cf867084f3ef09075a605847fec54715eeccaf1510f0f49d0cd68bfd83535f99"}, + {file = "aiocsv-1.2.5-cp37-cp37m-win_amd64.whl", hash = "sha256:b8db0fc1269e9b432616eb5af90f896188b93ea6b971524a1216145070c43e4b"}, + {file = "aiocsv-1.2.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2a6b99770d044a59de244ad2f0c5de8461a7bbf689277a46f9251e95e0909c88"}, + {file = "aiocsv-1.2.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f84f92ed95f4fb0b59e377f6b400a2b252b613c8319c1005add1b33ab052fd77"}, + {file = "aiocsv-1.2.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:72a302a7f6f80fabfc3c36273d8cee2782245bd1cceb6cc8bbd1ea611905498b"}, + {file = "aiocsv-1.2.5-cp38-cp38-win_amd64.whl", hash = "sha256:9fa70db03e3c4dc053c2fc469c2d7cfaedfcf254bd9ad90bdf08ba021fc0909e"}, + {file = "aiocsv-1.2.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d4c285f01e18fdd47381cb72a8e18f2ce02ecfe36f02976f038ef9c5e0fbc770"}, + {file = "aiocsv-1.2.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c9064f0ed61b63af0ca26d32b78c790e8a9f5b2e2907b04b6021b2c7de6e1e3"}, + {file = "aiocsv-1.2.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c7a959f40131bf8cc598e93e542fc341a56062e39254ca35f4f61fc3d17d01aa"}, + {file = "aiocsv-1.2.5-cp39-cp39-win_amd64.whl", hash = "sha256:53544ba47224d67f4123bae894de77fd89a4472b98873da86d5814d44f7c4a41"}, + {file = "aiocsv-1.2.5.tar.gz", hash = "sha256:807a61335ff3b461e84abcdb68445207d1dbd518d046f570a0048f4fcb0bb8ec"}, ] [[package]] name = "aiofiles" -version = "0.8.0" +version = "23.2.1" description = "File support for asyncio." -category = "main" optional = false -python-versions = ">=3.6,<4.0" +python-versions = ">=3.7" +groups = ["main"] files = [ - {file = "aiofiles-0.8.0-py3-none-any.whl", hash = "sha256:7a973fc22b29e9962d0897805ace5856e6a566ab1f0c8e5c91ff6c866519c937"}, - {file = "aiofiles-0.8.0.tar.gz", hash = "sha256:8334f23235248a3b2e83b2c3a78a22674f39969b96397126cc93664d9a901e59"}, + {file = "aiofiles-23.2.1-py3-none-any.whl", hash = "sha256:19297512c647d4b27a2cf7c34caa7e405c0d60b5560618a29a9fe027b18b0107"}, + {file = "aiofiles-23.2.1.tar.gz", hash = "sha256:84ec2218d8419404abcb9f0c02df3f34c6e0a68ed41072acfb1cef5cbc29051a"}, ] [[package]] name = "anyio" -version = "3.7.0" +version = "4.9.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["main", "dev"] files = [ - {file = "anyio-3.7.0-py3-none-any.whl", hash = "sha256:eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0"}, - {file = "anyio-3.7.0.tar.gz", hash = "sha256:275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce"}, + {file = "anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c"}, + {file = "anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028"}, ] [package.dependencies] -exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} idna = ">=2.8" sniffio = ">=1.1" +typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} [package.extras] -doc = ["Sphinx (>=6.1.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme", "sphinxcontrib-jquery"] -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)"] -trio = ["trio (<0.22)"] +doc = ["Sphinx (>=8.2,<9.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"] +test = ["anyio[trio]", "blockbuster (>=1.5.23)", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\" and python_version < \"3.14\""] +trio = ["trio (>=0.26.1)"] [[package]] name = "asgiref" -version = "3.7.2" +version = "3.8.1" description = "ASGI specs, helper code, and adapters" -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "asgiref-3.7.2-py3-none-any.whl", hash = "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e"}, - {file = "asgiref-3.7.2.tar.gz", hash = "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed"}, + {file = "asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47"}, + {file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"}, ] [package.dependencies] @@ -106,9 +107,9 @@ tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] name = "astor" version = "0.8.1" description = "Read/rewrite/write Python ASTs" -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +groups = ["dev"] files = [ {file = "astor-0.8.1-py2.py3-none-any.whl", hash = "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5"}, {file = "astor-0.8.1.tar.gz", hash = "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e"}, @@ -116,44 +117,47 @@ files = [ [[package]] name = "attrs" -version = "23.1.0" +version = "25.3.0" description = "Classes Without Boilerplate" -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, - {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, + {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, + {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, ] [package.extras] -cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]", "pre-commit"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] -tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] +tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] [[package]] name = "autoflake" -version = "1.4" +version = "1.7.8" description = "Removes unused imports and unused variables" -category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.7" +groups = ["dev"] files = [ - {file = "autoflake-1.4.tar.gz", hash = "sha256:61a353012cff6ab94ca062823d1fb2f692c4acda51c76ff83a8d77915fba51ea"}, + {file = "autoflake-1.7.8-py3-none-any.whl", hash = "sha256:46373ef69b6714f5064c923bb28bd797c4f8a9497f557d87fc36665c6d956b39"}, + {file = "autoflake-1.7.8.tar.gz", hash = "sha256:e7e46372dee46fa1c97acf310d99d922b63d369718a270809d7c278d34a194cf"}, ] [package.dependencies] -pyflakes = ">=1.1.0" +pyflakes = ">=1.1.0,<3" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} [[package]] name = "bandit" version = "1.7.2" description = "Security oriented static analyser for python code." -category = "dev" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "bandit-1.7.2-py3-none-any.whl", hash = "sha256:e20402cadfd126d85b68ed4c8862959663c8c372dbbb1fca8f8e2c9f55a067ec"}, {file = "bandit-1.7.2.tar.gz", hash = "sha256:6d11adea0214a43813887bfe71a377b5a9955e4c826c8ffd341b494e3ab25260"}, @@ -174,9 +178,9 @@ yaml = ["PyYAML"] name = "black" version = "22.3.0" description = "The uncompromising code formatter." -category = "dev" optional = false python-versions = ">=3.6.2" +groups = ["dev"] files = [ {file = "black-22.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09"}, {file = "black-22.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb"}, @@ -219,111 +223,128 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "certifi" -version = "2023.5.7" +version = "2025.4.26" description = "Python package for providing Mozilla's CA Bundle." -category = "main" optional = false python-versions = ">=3.6" +groups = ["main", "dev"] files = [ - {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"}, - {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"}, + {file = "certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3"}, + {file = "certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6"}, ] [[package]] name = "charset-normalizer" -version = "3.1.0" +version = "3.4.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "dev" -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, - {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-win32.whl", hash = "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a"}, + {file = "charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a"}, + {file = "charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c"}, + {file = "charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7"}, + {file = "charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-win32.whl", hash = "sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58"}, + {file = "charset_normalizer-3.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-win32.whl", hash = "sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7"}, + {file = "charset_normalizer-3.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-win32.whl", hash = "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471"}, + {file = "charset_normalizer-3.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e"}, + {file = "charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0"}, + {file = "charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63"}, ] [[package]] name = "click" -version = "8.1.3" +version = "8.1.8" description = "Composable command line interface toolkit" -category = "dev" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, + {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, + {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, ] [package.dependencies] @@ -333,97 +354,101 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["main", "dev"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +markers = {main = "sys_platform == \"win32\"", dev = "platform_system == \"Windows\" or sys_platform == \"win32\""} [[package]] name = "coverage" -version = "7.2.7" +version = "7.8.0" description = "Code coverage measurement for Python" -category = "dev" optional = false -python-versions = ">=3.7" -files = [ - {file = "coverage-7.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8"}, - {file = "coverage-7.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb"}, - {file = "coverage-7.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6"}, - {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2"}, - {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"}, - {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1"}, - {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353"}, - {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495"}, - {file = "coverage-7.2.7-cp310-cp310-win32.whl", hash = "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818"}, - {file = "coverage-7.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850"}, - {file = "coverage-7.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f"}, - {file = "coverage-7.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe"}, - {file = "coverage-7.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3"}, - {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f"}, - {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"}, - {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833"}, - {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97"}, - {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a"}, - {file = "coverage-7.2.7-cp311-cp311-win32.whl", hash = "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a"}, - {file = "coverage-7.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562"}, - {file = "coverage-7.2.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4"}, - {file = "coverage-7.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4"}, - {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01"}, - {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"}, - {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d"}, - {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de"}, - {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d"}, - {file = "coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511"}, - {file = "coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3"}, - {file = "coverage-7.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f"}, - {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb"}, - {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9"}, - {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"}, - {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a"}, - {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959"}, - {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02"}, - {file = "coverage-7.2.7-cp37-cp37m-win32.whl", hash = "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f"}, - {file = "coverage-7.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0"}, - {file = "coverage-7.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5"}, - {file = "coverage-7.2.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5"}, - {file = "coverage-7.2.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9"}, - {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6"}, - {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"}, - {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050"}, - {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5"}, - {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f"}, - {file = "coverage-7.2.7-cp38-cp38-win32.whl", hash = "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e"}, - {file = "coverage-7.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c"}, - {file = "coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9"}, - {file = "coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2"}, - {file = "coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7"}, - {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e"}, - {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"}, - {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9"}, - {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250"}, - {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2"}, - {file = "coverage-7.2.7-cp39-cp39-win32.whl", hash = "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb"}, - {file = "coverage-7.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27"}, - {file = "coverage-7.2.7-pp37.pp38.pp39-none-any.whl", hash = "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d"}, - {file = "coverage-7.2.7.tar.gz", hash = "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59"}, +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "coverage-7.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2931f66991175369859b5fd58529cd4b73582461877ecfd859b6549869287ffe"}, + {file = "coverage-7.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52a523153c568d2c0ef8826f6cc23031dc86cffb8c6aeab92c4ff776e7951b28"}, + {file = "coverage-7.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c8a5c139aae4c35cbd7cadca1df02ea8cf28a911534fc1b0456acb0b14234f3"}, + {file = "coverage-7.8.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a26c0c795c3e0b63ec7da6efded5f0bc856d7c0b24b2ac84b4d1d7bc578d676"}, + {file = "coverage-7.8.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:821f7bcbaa84318287115d54becb1915eece6918136c6f91045bb84e2f88739d"}, + {file = "coverage-7.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a321c61477ff8ee705b8a5fed370b5710c56b3a52d17b983d9215861e37b642a"}, + {file = "coverage-7.8.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:ed2144b8a78f9d94d9515963ed273d620e07846acd5d4b0a642d4849e8d91a0c"}, + {file = "coverage-7.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:042e7841a26498fff7a37d6fda770d17519982f5b7d8bf5278d140b67b61095f"}, + {file = "coverage-7.8.0-cp310-cp310-win32.whl", hash = "sha256:f9983d01d7705b2d1f7a95e10bbe4091fabc03a46881a256c2787637b087003f"}, + {file = "coverage-7.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:5a570cd9bd20b85d1a0d7b009aaf6c110b52b5755c17be6962f8ccd65d1dbd23"}, + {file = "coverage-7.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7ac22a0bb2c7c49f441f7a6d46c9c80d96e56f5a8bc6972529ed43c8b694e27"}, + {file = "coverage-7.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf13d564d310c156d1c8e53877baf2993fb3073b2fc9f69790ca6a732eb4bfea"}, + {file = "coverage-7.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5761c70c017c1b0d21b0815a920ffb94a670c8d5d409d9b38857874c21f70d7"}, + {file = "coverage-7.8.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5ff52d790c7e1628241ffbcaeb33e07d14b007b6eb00a19320c7b8a7024c040"}, + {file = "coverage-7.8.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d39fc4817fd67b3915256af5dda75fd4ee10621a3d484524487e33416c6f3543"}, + {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b44674870709017e4b4036e3d0d6c17f06a0e6d4436422e0ad29b882c40697d2"}, + {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8f99eb72bf27cbb167b636eb1726f590c00e1ad375002230607a844d9e9a2318"}, + {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b571bf5341ba8c6bc02e0baeaf3b061ab993bf372d982ae509807e7f112554e9"}, + {file = "coverage-7.8.0-cp311-cp311-win32.whl", hash = "sha256:e75a2ad7b647fd8046d58c3132d7eaf31b12d8a53c0e4b21fa9c4d23d6ee6d3c"}, + {file = "coverage-7.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:3043ba1c88b2139126fc72cb48574b90e2e0546d4c78b5299317f61b7f718b78"}, + {file = "coverage-7.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bbb5cc845a0292e0c520656d19d7ce40e18d0e19b22cb3e0409135a575bf79fc"}, + {file = "coverage-7.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4dfd9a93db9e78666d178d4f08a5408aa3f2474ad4d0e0378ed5f2ef71640cb6"}, + {file = "coverage-7.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f017a61399f13aa6d1039f75cd467be388d157cd81f1a119b9d9a68ba6f2830d"}, + {file = "coverage-7.8.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0915742f4c82208ebf47a2b154a5334155ed9ef9fe6190674b8a46c2fb89cb05"}, + {file = "coverage-7.8.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a40fcf208e021eb14b0fac6bdb045c0e0cab53105f93ba0d03fd934c956143a"}, + {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a1f406a8e0995d654b2ad87c62caf6befa767885301f3b8f6f73e6f3c31ec3a6"}, + {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:77af0f6447a582fdc7de5e06fa3757a3ef87769fbb0fdbdeba78c23049140a47"}, + {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f2d32f95922927186c6dbc8bc60df0d186b6edb828d299ab10898ef3f40052fe"}, + {file = "coverage-7.8.0-cp312-cp312-win32.whl", hash = "sha256:769773614e676f9d8e8a0980dd7740f09a6ea386d0f383db6821df07d0f08545"}, + {file = "coverage-7.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:e5d2b9be5b0693cf21eb4ce0ec8d211efb43966f6657807f6859aab3814f946b"}, + {file = "coverage-7.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ac46d0c2dd5820ce93943a501ac5f6548ea81594777ca585bf002aa8854cacd"}, + {file = "coverage-7.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:771eb7587a0563ca5bb6f622b9ed7f9d07bd08900f7589b4febff05f469bea00"}, + {file = "coverage-7.8.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42421e04069fb2cbcbca5a696c4050b84a43b05392679d4068acbe65449b5c64"}, + {file = "coverage-7.8.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:554fec1199d93ab30adaa751db68acec2b41c5602ac944bb19187cb9a41a8067"}, + {file = "coverage-7.8.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aaeb00761f985007b38cf463b1d160a14a22c34eb3f6a39d9ad6fc27cb73008"}, + {file = "coverage-7.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:581a40c7b94921fffd6457ffe532259813fc68eb2bdda60fa8cc343414ce3733"}, + {file = "coverage-7.8.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f319bae0321bc838e205bf9e5bc28f0a3165f30c203b610f17ab5552cff90323"}, + {file = "coverage-7.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:04bfec25a8ef1c5f41f5e7e5c842f6b615599ca8ba8391ec33a9290d9d2db3a3"}, + {file = "coverage-7.8.0-cp313-cp313-win32.whl", hash = "sha256:dd19608788b50eed889e13a5d71d832edc34fc9dfce606f66e8f9f917eef910d"}, + {file = "coverage-7.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:a9abbccd778d98e9c7e85038e35e91e67f5b520776781d9a1e2ee9d400869487"}, + {file = "coverage-7.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:18c5ae6d061ad5b3e7eef4363fb27a0576012a7447af48be6c75b88494c6cf25"}, + {file = "coverage-7.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:95aa6ae391a22bbbce1b77ddac846c98c5473de0372ba5c463480043a07bff42"}, + {file = "coverage-7.8.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e013b07ba1c748dacc2a80e69a46286ff145935f260eb8c72df7185bf048f502"}, + {file = "coverage-7.8.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d766a4f0e5aa1ba056ec3496243150698dc0481902e2b8559314368717be82b1"}, + {file = "coverage-7.8.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad80e6b4a0c3cb6f10f29ae4c60e991f424e6b14219d46f1e7d442b938ee68a4"}, + {file = "coverage-7.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b87eb6fc9e1bb8f98892a2458781348fa37e6925f35bb6ceb9d4afd54ba36c73"}, + {file = "coverage-7.8.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d1ba00ae33be84066cfbe7361d4e04dec78445b2b88bdb734d0d1cbab916025a"}, + {file = "coverage-7.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f3c38e4e5ccbdc9198aecc766cedbb134b2d89bf64533973678dfcf07effd883"}, + {file = "coverage-7.8.0-cp313-cp313t-win32.whl", hash = "sha256:379fe315e206b14e21db5240f89dc0774bdd3e25c3c58c2c733c99eca96f1ada"}, + {file = "coverage-7.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2e4b6b87bb0c846a9315e3ab4be2d52fac905100565f4b92f02c445c8799e257"}, + {file = "coverage-7.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa260de59dfb143af06dcf30c2be0b200bed2a73737a8a59248fcb9fa601ef0f"}, + {file = "coverage-7.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:96121edfa4c2dfdda409877ea8608dd01de816a4dc4a0523356067b305e4e17a"}, + {file = "coverage-7.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b8af63b9afa1031c0ef05b217faa598f3069148eeee6bb24b79da9012423b82"}, + {file = "coverage-7.8.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:89b1f4af0d4afe495cd4787a68e00f30f1d15939f550e869de90a86efa7e0814"}, + {file = "coverage-7.8.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94ec0be97723ae72d63d3aa41961a0b9a6f5a53ff599813c324548d18e3b9e8c"}, + {file = "coverage-7.8.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8a1d96e780bdb2d0cbb297325711701f7c0b6f89199a57f2049e90064c29f6bd"}, + {file = "coverage-7.8.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f1d8a2a57b47142b10374902777e798784abf400a004b14f1b0b9eaf1e528ba4"}, + {file = "coverage-7.8.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cf60dd2696b457b710dd40bf17ad269d5f5457b96442f7f85722bdb16fa6c899"}, + {file = "coverage-7.8.0-cp39-cp39-win32.whl", hash = "sha256:be945402e03de47ba1872cd5236395e0f4ad635526185a930735f66710e1bd3f"}, + {file = "coverage-7.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:90e7fbc6216ecaffa5a880cdc9c77b7418c1dcb166166b78dbc630d07f278cc3"}, + {file = "coverage-7.8.0-pp39.pp310.pp311-none-any.whl", hash = "sha256:b8194fb8e50d556d5849753de991d390c5a1edeeba50f68e3a9253fbd8bf8ccd"}, + {file = "coverage-7.8.0-py3-none-any.whl", hash = "sha256:dbf364b4c5e7bae9250528167dfe40219b62e2d573c854d74be213e1e52069f7"}, + {file = "coverage-7.8.0.tar.gz", hash = "sha256:7a3d62b3b03b4b6fd41a085f3574874cf946cb4604d2b4d3e8dca8cd570ca501"}, ] [package.dependencies] tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} [package.extras] -toml = ["tomli"] +toml = ["tomli ; python_full_version <= \"3.11.0a6\""] [[package]] name = "darglint" version = "1.8.1" description = "A utility for ensuring Google-style docstrings stay up to date with the source code." -category = "dev" optional = false python-versions = ">=3.6,<4.0" +groups = ["dev"] files = [ {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"}, {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"}, @@ -431,40 +456,44 @@ files = [ [[package]] name = "docutils" -version = "0.20.1" +version = "0.21.2" description = "Docutils -- Python Documentation Utilities" -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, - {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, + {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, + {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, ] [[package]] name = "eradicate" -version = "2.2.0" +version = "2.3.0" description = "Removes commented-out code." -category = "dev" optional = false python-versions = "*" +groups = ["dev"] files = [ - {file = "eradicate-2.2.0-py3-none-any.whl", hash = "sha256:751813c315a48ce7e3d0483410991015342d380a956e86e0265c61bfb875bcbc"}, - {file = "eradicate-2.2.0.tar.gz", hash = "sha256:c329a05def6a4b558dab58bb1b694f5209706b7c99ba174d226dfdb69a5ba0da"}, + {file = "eradicate-2.3.0-py3-none-any.whl", hash = "sha256:2b29b3dd27171f209e4ddd8204b70c02f0682ae95eecb353f10e8d72b149c63e"}, + {file = "eradicate-2.3.0.tar.gz", hash = "sha256:06df115be3b87d0fc1c483db22a2ebb12bcf40585722810d809cc770f5031c37"}, ] [[package]] name = "exceptiongroup" -version = "1.1.1" +version = "1.3.0" description = "Backport of PEP 654 (exception groups)" -category = "main" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] +markers = "python_version < \"3.11\"" files = [ - {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, - {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, + {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}, + {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}, ] +[package.dependencies] +typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} + [package.extras] test = ["pytest (>=6)"] @@ -472,9 +501,9 @@ test = ["pytest (>=6)"] name = "fastapi" version = "0.95.2" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" -category = "dev" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "fastapi-0.95.2-py3-none-any.whl", hash = "sha256:d374dbc4ef2ad9b803899bd3360d34c534adc574546e25314ab72c0c4411749f"}, {file = "fastapi-0.95.2.tar.gz", hash = "sha256:4d9d3e8c71c73f11874bcf5e33626258d143252e329a01002f767306c64fb982"}, @@ -494,9 +523,9 @@ test = ["anyio[trio] (>=3.2.1,<4.0.0)", "black (==23.1.0)", "coverage[toml] (>=6 name = "flake8" version = "4.0.1" description = "the modular source code checker: pep8 pyflakes and co" -category = "dev" optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, @@ -511,9 +540,9 @@ pyflakes = ">=2.4.0,<2.5.0" name = "flake8-bandit" version = "2.1.2" description = "Automated security testing with bandit and flake8." -category = "dev" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "flake8_bandit-2.1.2.tar.gz", hash = "sha256:687fc8da2e4a239b206af2e54a90093572a60d0954f3054e23690739b0b0de3b"}, ] @@ -528,9 +557,9 @@ pycodestyle = "*" name = "flake8-broken-line" version = "0.4.0" description = "Flake8 plugin to forbid backslashes for line breaks" -category = "dev" optional = false python-versions = ">=3.6,<4.0" +groups = ["dev"] files = [ {file = "flake8-broken-line-0.4.0.tar.gz", hash = "sha256:771aab5aa0997666796fed249d0e48e6c01cdfeca8c95521eea28a38b7ced4c7"}, {file = "flake8_broken_line-0.4.0-py3-none-any.whl", hash = "sha256:e9c522856862239a2c7ef2c1de0276fa598572aa864bd4e9c7efc2a827538515"}, @@ -543,9 +572,9 @@ flake8 = ">=3.5,<5" name = "flake8-bugbear" version = "21.11.29" description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." -category = "dev" optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "flake8-bugbear-21.11.29.tar.gz", hash = "sha256:8b04cb2fafc6a78e1a9d873bd3988e4282f7959bb6b0d7c1ae648ec09b937a7b"}, {file = "flake8_bugbear-21.11.29-py36.py37.py38-none-any.whl", hash = "sha256:179e41ddae5de5e3c20d1f61736feeb234e70958fbb56ab3c28a67739c8e9a82"}, @@ -562,9 +591,9 @@ dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit"] name = "flake8-commas" version = "2.1.0" description = "Flake8 lint for trailing commas." -category = "dev" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "flake8-commas-2.1.0.tar.gz", hash = "sha256:940441ab8ee544df564ae3b3f49f20462d75d5c7cac2463e0b27436e2050f263"}, {file = "flake8_commas-2.1.0-py2.py3-none-any.whl", hash = "sha256:ebb96c31e01d0ef1d0685a21f3f0e2f8153a0381430e748bf0bbbb5d5b453d54"}, @@ -575,26 +604,26 @@ flake8 = ">=2" [[package]] name = "flake8-comprehensions" -version = "3.12.0" +version = "3.16.0" description = "A flake8 plugin to help you write better list/set/dict comprehensions." -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "flake8_comprehensions-3.12.0-py3-none-any.whl", hash = "sha256:013234637ec7dfcb7cd2900578fb53c512f81db909cefe371c019232695c362d"}, - {file = "flake8_comprehensions-3.12.0.tar.gz", hash = "sha256:419ef1a6e8de929203791a5e8ff5e3906caeba13eb3290eebdbf88a9078d502e"}, + {file = "flake8_comprehensions-3.16.0-py3-none-any.whl", hash = "sha256:7c1eadc9d22e765f39857798febe7766b4d9c519793c6c149e3e13bf99693f70"}, + {file = "flake8_comprehensions-3.16.0.tar.gz", hash = "sha256:9cbf789905a8f03f9d350fb82b17b264d9a16c7ce3542b2a7b871ef568cafabe"}, ] [package.dependencies] -flake8 = ">=3.0,<3.2.0 || >3.2.0" +flake8 = ">=3,<3.2 || >3.2" [[package]] name = "flake8-debugger" version = "4.1.2" description = "ipdb/pdb statement checker plugin for flake8" -category = "dev" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "flake8-debugger-4.1.2.tar.gz", hash = "sha256:52b002560941e36d9bf806fca2523dc7fb8560a295d5f1a6e15ac2ded7a73840"}, {file = "flake8_debugger-4.1.2-py3-none-any.whl", hash = "sha256:0a5e55aeddcc81da631ad9c8c366e7318998f83ff00985a49e6b3ecf61e571bf"}, @@ -608,9 +637,9 @@ pycodestyle = "*" name = "flake8-docstrings" version = "1.7.0" description = "Extension for flake8 which uses pydocstyle to check docstrings" -category = "dev" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "flake8_docstrings-1.7.0-py2.py3-none-any.whl", hash = "sha256:51f2344026da083fc084166a9353f5082b01f72901df422f74b4d953ae88ac75"}, {file = "flake8_docstrings-1.7.0.tar.gz", hash = "sha256:4c8cc748dc16e6869728699e5d0d685da9a10b0ea718e090b1ba088e67a941af"}, @@ -624,9 +653,9 @@ pydocstyle = ">=2.1" name = "flake8-eradicate" version = "1.4.0" description = "Flake8 plugin to find commented out code" -category = "dev" optional = false python-versions = ">=3.7,<4.0" +groups = ["dev"] files = [ {file = "flake8-eradicate-1.4.0.tar.gz", hash = "sha256:3088cfd6717d1c9c6c3ac45ef2e5f5b6c7267f7504d5a74b781500e95cb9c7e1"}, {file = "flake8_eradicate-1.4.0-py3-none-any.whl", hash = "sha256:e3bbd0871be358e908053c1ab728903c114f062ba596b4d40c852fd18f473d56"}, @@ -641,9 +670,9 @@ flake8 = ">=3.5,<6" name = "flake8-isort" version = "4.2.0" description = "flake8 plugin that integrates isort ." -category = "dev" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "flake8-isort-4.2.0.tar.gz", hash = "sha256:26571500cd54976bbc0cf1006ffbcd1a68dd102f816b7a1051b219616ba9fee0"}, {file = "flake8_isort-4.2.0-py3-none-any.whl", hash = "sha256:5b87630fb3719bf4c1833fd11e0d9534f43efdeba524863e15d8f14a7ef6adbf"}, @@ -660,9 +689,9 @@ test = ["pytest-cov"] name = "flake8-polyfill" version = "1.0.2" description = "Polyfill package for Flake8 plugins" -category = "dev" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "flake8-polyfill-1.0.2.tar.gz", hash = "sha256:e44b087597f6da52ec6393a709e7108b2905317d0c0b744cdca6208e670d8eda"}, {file = "flake8_polyfill-1.0.2-py2.py3-none-any.whl", hash = "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9"}, @@ -673,25 +702,26 @@ flake8 = "*" [[package]] name = "flake8-quotes" -version = "3.3.2" +version = "3.4.0" description = "Flake8 lint for quotes." -category = "dev" optional = false python-versions = "*" +groups = ["dev"] files = [ - {file = "flake8-quotes-3.3.2.tar.gz", hash = "sha256:6e26892b632dacba517bf27219c459a8396dcfac0f5e8204904c5a4ba9b480e1"}, + {file = "flake8-quotes-3.4.0.tar.gz", hash = "sha256:aad8492fb710a2d3eabe68c5f86a1428de650c8484127e14c43d0504ba30276c"}, ] [package.dependencies] flake8 = "*" +setuptools = "*" [[package]] name = "flake8-rst-docstrings" version = "0.2.7" description = "Python docstring reStructuredText (RST) validator" -category = "dev" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "flake8-rst-docstrings-0.2.7.tar.gz", hash = "sha256:2740067ab9237559dd45a3434d8c987792c7b259ca563621a3b95efe201f5382"}, {file = "flake8_rst_docstrings-0.2.7-py3-none-any.whl", hash = "sha256:5d56075dce360bcc9c6775bfe7cb431aa395de600ca7e8d40580a28d50b2a803"}, @@ -706,9 +736,9 @@ restructuredtext-lint = "*" name = "flake8-string-format" version = "0.3.0" description = "string format checker, plugin for flake8" -category = "dev" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "flake8-string-format-0.3.0.tar.gz", hash = "sha256:65f3da786a1461ef77fca3780b314edb2853c377f2e35069723348c8917deaa2"}, {file = "flake8_string_format-0.3.0-py2.py3-none-any.whl", hash = "sha256:812ff431f10576a74c89be4e85b8e075a705be39bc40c4b4278b5b13e2afa9af"}, @@ -719,14 +749,14 @@ flake8 = "*" [[package]] name = "gitdb" -version = "4.0.10" +version = "4.0.12" description = "Git Object Database" -category = "dev" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ - {file = "gitdb-4.0.10-py3-none-any.whl", hash = "sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7"}, - {file = "gitdb-4.0.10.tar.gz", hash = "sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a"}, + {file = "gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf"}, + {file = "gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571"}, ] [package.dependencies] @@ -734,108 +764,116 @@ smmap = ">=3.0.1,<6" [[package]] name = "gitpython" -version = "3.1.31" +version = "3.1.44" description = "GitPython is a Python library used to interact with Git repositories" -category = "dev" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ - {file = "GitPython-3.1.31-py3-none-any.whl", hash = "sha256:f04893614f6aa713a60cbbe1e6a97403ef633103cdd0ef5eb6efe0deb98dbe8d"}, - {file = "GitPython-3.1.31.tar.gz", hash = "sha256:8ce3bcf69adfdf7c7d503e78fd3b1c492af782d58893b650adb2ac8912ddd573"}, + {file = "GitPython-3.1.44-py3-none-any.whl", hash = "sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110"}, + {file = "gitpython-3.1.44.tar.gz", hash = "sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269"}, ] [package.dependencies] gitdb = ">=4.0.1,<5" +[package.extras] +doc = ["sphinx (>=7.1.2,<7.2)", "sphinx-autodoc-typehints", "sphinx_rtd_theme"] +test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock ; python_version < \"3.8\"", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions ; python_version < \"3.11\""] + [[package]] name = "h11" -version = "0.12.0" +version = "0.16.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" +groups = ["main", "dev"] files = [ - {file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"}, - {file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"}, + {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, + {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, ] [[package]] name = "httpcore" -version = "0.15.0" +version = "1.0.9" description = "A minimal low-level HTTP client." -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["main", "dev"] files = [ - {file = "httpcore-0.15.0-py3-none-any.whl", hash = "sha256:1105b8b73c025f23ff7c36468e4432226cbb959176eab66864b8e31c4ee27fa6"}, - {file = "httpcore-0.15.0.tar.gz", hash = "sha256:18b68ab86a3ccf3e7dc0f43598eaddcf472b602aba29f9aa6ab85fe2ada3980b"}, + {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, + {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, ] [package.dependencies] -anyio = ">=3.0.0,<4.0.0" certifi = "*" -h11 = ">=0.11,<0.13" -sniffio = ">=1.0.0,<2.0.0" +h11 = ">=0.16" [package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] http2 = ["h2 (>=3,<5)"] -socks = ["socksio (>=1.0.0,<2.0.0)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<1.0)"] [[package]] name = "httpx" -version = "0.23.0" +version = "0.25.2" description = "The next generation HTTP client." -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["main", "dev"] files = [ - {file = "httpx-0.23.0-py3-none-any.whl", hash = "sha256:42974f577483e1e932c3cdc3cd2303e883cbfba17fe228b0f63589764d7b9c4b"}, - {file = "httpx-0.23.0.tar.gz", hash = "sha256:f28eac771ec9eb4866d3fb4ab65abd42d38c424739e80c08d8d20570de60b0ef"}, + {file = "httpx-0.25.2-py3-none-any.whl", hash = "sha256:a05d3d052d9b2dfce0e3896636467f8a5342fb2b902c819428e1ac65413ca118"}, + {file = "httpx-0.25.2.tar.gz", hash = "sha256:8b8fcaa0c8ea7b05edd69a094e63a2094c4efcb48129fb757361bc423c0ad9e8"}, ] [package.dependencies] +anyio = "*" certifi = "*" -httpcore = ">=0.15.0,<0.16.0" -rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]} +httpcore = "==1.*" +idna = "*" sniffio = "*" [package.extras] -brotli = ["brotli", "brotlicffi"] -cli = ["click (>=8.0.0,<9.0.0)", "pygments (>=2.0.0,<3.0.0)", "rich (>=10,<13)"] +brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] http2 = ["h2 (>=3,<5)"] -socks = ["socksio (>=1.0.0,<2.0.0)"] +socks = ["socksio (==1.*)"] [[package]] name = "idna" -version = "3.4" +version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" +groups = ["main", "dev"] files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, ] +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + [[package]] name = "iniconfig" -version = "2.0.0" +version = "2.1.0" description = "brain-dead simple config-ini parsing" -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, + {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, + {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, ] [[package]] name = "isort" version = "5.10.1" description = "A Python utility / library to sort Python imports." -category = "dev" optional = false python-versions = ">=3.6.1,<4.0" +groups = ["dev"] files = [ {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, @@ -851,9 +889,9 @@ requirements-deprecated-finder = ["pip-api", "pipreqs"] name = "loguru" version = "0.6.0" description = "Python logging made (stupidly) simple" -category = "main" optional = false python-versions = ">=3.5" +groups = ["main"] files = [ {file = "loguru-0.6.0-py3-none-any.whl", hash = "sha256:4e2414d534a2ab57573365b3e6d0234dfb1d84b68b7f3b948e6fb743860a77c3"}, {file = "loguru-0.6.0.tar.gz", hash = "sha256:066bd06758d0a513e9836fd9c6b5a75bfb3fd36841f4b996bc60b547a309d41c"}, @@ -864,15 +902,15 @@ colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} [package.extras] -dev = ["Sphinx (>=4.1.1)", "black (>=19.10b0)", "colorama (>=0.3.4)", "docutils (==0.16)", "flake8 (>=3.7.7)", "isort (>=5.1.1)", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "sphinx-autobuild (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "tox (>=3.9.0)"] +dev = ["Sphinx (>=4.1.1) ; python_version >= \"3.6\"", "black (>=19.10b0) ; python_version >= \"3.6\"", "colorama (>=0.3.4)", "docutils (==0.16)", "flake8 (>=3.7.7)", "isort (>=5.1.1) ; python_version >= \"3.6\"", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "sphinx-autobuild (>=0.7.1) ; python_version >= \"3.6\"", "sphinx-rtd-theme (>=0.4.3) ; python_version >= \"3.6\"", "tox (>=3.9.0)"] [[package]] name = "mccabe" version = "0.6.1" description = "McCabe checker, plugin for flake8" -category = "dev" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, @@ -882,9 +920,9 @@ files = [ name = "mypy" version = "0.910" description = "Optional static typing for Python" -category = "dev" optional = false python-versions = ">=3.5" +groups = ["dev"] files = [ {file = "mypy-0.910-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:a155d80ea6cee511a3694b108c4494a39f42de11ee4e61e72bc424c490e46457"}, {file = "mypy-0.910-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b94e4b785e304a04ea0828759172a15add27088520dc7e49ceade7834275bedb"}, @@ -924,56 +962,59 @@ python2 = ["typed-ast (>=1.4.0,<1.5.0)"] name = "mypy-extensions" version = "0.4.4" description = "Experimental type system extensions for programs checked with the mypy typechecker." -category = "main" optional = false python-versions = ">=2.7" +groups = ["main", "dev"] files = [ {file = "mypy_extensions-0.4.4.tar.gz", hash = "sha256:c8b707883a96efe9b4bb3aaf0dcc07e7e217d7d8368eec4db4049ee9e142f4fd"}, ] [[package]] name = "packaging" -version = "23.1" +version = "25.0" description = "Core utilities for Python packages" -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, - {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, + {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, + {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, ] [[package]] name = "pathspec" -version = "0.11.1" +version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, - {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, ] [[package]] name = "pbr" -version = "5.11.1" +version = "6.1.1" description = "Python Build Reasonableness" -category = "dev" optional = false python-versions = ">=2.6" +groups = ["dev"] files = [ - {file = "pbr-5.11.1-py2.py3-none-any.whl", hash = "sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b"}, - {file = "pbr-5.11.1.tar.gz", hash = "sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3"}, + {file = "pbr-6.1.1-py2.py3-none-any.whl", hash = "sha256:38d4daea5d9fa63b3f626131b9d34947fd0c8be9b05a29276870580050a25a76"}, + {file = "pbr-6.1.1.tar.gz", hash = "sha256:93ea72ce6989eb2eed99d0f75721474f69ad88128afdef5ac377eb797c4bf76b"}, ] +[package.dependencies] +setuptools = "*" + [[package]] name = "pep8-naming" version = "0.12.1" description = "Check PEP-8 naming conventions, plugin for flake8" -category = "dev" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "pep8-naming-0.12.1.tar.gz", hash = "sha256:bb2455947757d162aa4cad55dba4ce029005cd1692f2899a21d51d8630ca7841"}, {file = "pep8_naming-0.12.1-py2.py3-none-any.whl", hash = "sha256:4a8daeaeb33cfcde779309fc0c9c0a68a3bbe2ad8a8308b763c5068f86eb9f37"}, @@ -985,30 +1026,31 @@ flake8-polyfill = ">=1.0.2,<2" [[package]] name = "platformdirs" -version = "3.5.1" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" +version = "4.3.8" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "platformdirs-3.5.1-py3-none-any.whl", hash = "sha256:e2378146f1964972c03c085bb5662ae80b2b8c06226c54b2ff4aa9483e8a13a5"}, - {file = "platformdirs-3.5.1.tar.gz", hash = "sha256:412dae91f52a6f84830f39a8078cecd0e866cb72294a5c66808e74d5e88d251f"}, + {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, + {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, ] [package.extras] -docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.2.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.14.1)"] [[package]] name = "pluggy" -version = "1.0.0" +version = "1.5.0" description = "plugin and hook calling mechanisms for python" -category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, ] [package.extras] @@ -1019,9 +1061,9 @@ testing = ["pytest", "pytest-benchmark"] name = "pycodestyle" version = "2.8.0" description = "Python style guide checker" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +groups = ["dev"] files = [ {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, @@ -1029,48 +1071,62 @@ files = [ [[package]] name = "pydantic" -version = "1.10.8" +version = "1.10.22" description = "Data validation and settings management using python type hints" -category = "main" optional = false python-versions = ">=3.7" -files = [ - {file = "pydantic-1.10.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1243d28e9b05003a89d72e7915fdb26ffd1d39bdd39b00b7dbe4afae4b557f9d"}, - {file = "pydantic-1.10.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0ab53b609c11dfc0c060d94335993cc2b95b2150e25583bec37a49b2d6c6c3f"}, - {file = "pydantic-1.10.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9613fadad06b4f3bc5db2653ce2f22e0de84a7c6c293909b48f6ed37b83c61f"}, - {file = "pydantic-1.10.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df7800cb1984d8f6e249351139667a8c50a379009271ee6236138a22a0c0f319"}, - {file = "pydantic-1.10.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:0c6fafa0965b539d7aab0a673a046466d23b86e4b0e8019d25fd53f4df62c277"}, - {file = "pydantic-1.10.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e82d4566fcd527eae8b244fa952d99f2ca3172b7e97add0b43e2d97ee77f81ab"}, - {file = "pydantic-1.10.8-cp310-cp310-win_amd64.whl", hash = "sha256:ab523c31e22943713d80d8d342d23b6f6ac4b792a1e54064a8d0cf78fd64e800"}, - {file = "pydantic-1.10.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:666bdf6066bf6dbc107b30d034615d2627e2121506c555f73f90b54a463d1f33"}, - {file = "pydantic-1.10.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:35db5301b82e8661fa9c505c800d0990bc14e9f36f98932bb1d248c0ac5cada5"}, - {file = "pydantic-1.10.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f90c1e29f447557e9e26afb1c4dbf8768a10cc676e3781b6a577841ade126b85"}, - {file = "pydantic-1.10.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93e766b4a8226e0708ef243e843105bf124e21331694367f95f4e3b4a92bbb3f"}, - {file = "pydantic-1.10.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:88f195f582851e8db960b4a94c3e3ad25692c1c1539e2552f3df7a9e972ef60e"}, - {file = "pydantic-1.10.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:34d327c81e68a1ecb52fe9c8d50c8a9b3e90d3c8ad991bfc8f953fb477d42fb4"}, - {file = "pydantic-1.10.8-cp311-cp311-win_amd64.whl", hash = "sha256:d532bf00f381bd6bc62cabc7d1372096b75a33bc197a312b03f5838b4fb84edd"}, - {file = "pydantic-1.10.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7d5b8641c24886d764a74ec541d2fc2c7fb19f6da2a4001e6d580ba4a38f7878"}, - {file = "pydantic-1.10.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b1f6cb446470b7ddf86c2e57cd119a24959af2b01e552f60705910663af09a4"}, - {file = "pydantic-1.10.8-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c33b60054b2136aef8cf190cd4c52a3daa20b2263917c49adad20eaf381e823b"}, - {file = "pydantic-1.10.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1952526ba40b220b912cdc43c1c32bcf4a58e3f192fa313ee665916b26befb68"}, - {file = "pydantic-1.10.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bb14388ec45a7a0dc429e87def6396f9e73c8c77818c927b6a60706603d5f2ea"}, - {file = "pydantic-1.10.8-cp37-cp37m-win_amd64.whl", hash = "sha256:16f8c3e33af1e9bb16c7a91fc7d5fa9fe27298e9f299cff6cb744d89d573d62c"}, - {file = "pydantic-1.10.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ced8375969673929809d7f36ad322934c35de4af3b5e5b09ec967c21f9f7887"}, - {file = "pydantic-1.10.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:93e6bcfccbd831894a6a434b0aeb1947f9e70b7468f274154d03d71fabb1d7c6"}, - {file = "pydantic-1.10.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:191ba419b605f897ede9892f6c56fb182f40a15d309ef0142212200a10af4c18"}, - {file = "pydantic-1.10.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:052d8654cb65174d6f9490cc9b9a200083a82cf5c3c5d3985db765757eb3b375"}, - {file = "pydantic-1.10.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ceb6a23bf1ba4b837d0cfe378329ad3f351b5897c8d4914ce95b85fba96da5a1"}, - {file = "pydantic-1.10.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f2e754d5566f050954727c77f094e01793bcb5725b663bf628fa6743a5a9108"}, - {file = "pydantic-1.10.8-cp38-cp38-win_amd64.whl", hash = "sha256:6a82d6cda82258efca32b40040228ecf43a548671cb174a1e81477195ed3ed56"}, - {file = "pydantic-1.10.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e59417ba8a17265e632af99cc5f35ec309de5980c440c255ab1ca3ae96a3e0e"}, - {file = "pydantic-1.10.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:84d80219c3f8d4cad44575e18404099c76851bc924ce5ab1c4c8bb5e2a2227d0"}, - {file = "pydantic-1.10.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e4148e635994d57d834be1182a44bdb07dd867fa3c2d1b37002000646cc5459"}, - {file = "pydantic-1.10.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12f7b0bf8553e310e530e9f3a2f5734c68699f42218bf3568ef49cd9b0e44df4"}, - {file = "pydantic-1.10.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42aa0c4b5c3025483240a25b09f3c09a189481ddda2ea3a831a9d25f444e03c1"}, - {file = "pydantic-1.10.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:17aef11cc1b997f9d574b91909fed40761e13fac438d72b81f902226a69dac01"}, - {file = "pydantic-1.10.8-cp39-cp39-win_amd64.whl", hash = "sha256:66a703d1983c675a6e0fed8953b0971c44dba48a929a2000a493c3772eb61a5a"}, - {file = "pydantic-1.10.8-py3-none-any.whl", hash = "sha256:7456eb22ed9aaa24ff3e7b4757da20d9e5ce2a81018c1b3ebd81a0b88a18f3b2"}, - {file = "pydantic-1.10.8.tar.gz", hash = "sha256:1410275520dfa70effadf4c21811d755e7ef9bb1f1d077a21958153a92c8d9ca"}, +groups = ["main", "dev"] +files = [ + {file = "pydantic-1.10.22-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:57889565ccc1e5b7b73343329bbe6198ebc472e3ee874af2fa1865cfe7048228"}, + {file = "pydantic-1.10.22-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:90729e22426de79bc6a3526b4c45ec4400caf0d4f10d7181ba7f12c01bb3897d"}, + {file = "pydantic-1.10.22-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8684d347f351554ec94fdcb507983d3116dc4577fb8799fed63c65869a2d10"}, + {file = "pydantic-1.10.22-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c8dad498ceff2d9ef1d2e2bc6608f5b59b8e1ba2031759b22dfb8c16608e1802"}, + {file = "pydantic-1.10.22-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fac529cc654d4575cf8de191cce354b12ba705f528a0a5c654de6d01f76cd818"}, + {file = "pydantic-1.10.22-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4148232aded8dd1dd13cf910a01b32a763c34bd79a0ab4d1ee66164fcb0b7b9d"}, + {file = "pydantic-1.10.22-cp310-cp310-win_amd64.whl", hash = "sha256:ece68105d9e436db45d8650dc375c760cc85a6793ae019c08769052902dca7db"}, + {file = "pydantic-1.10.22-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8e530a8da353f791ad89e701c35787418605d35085f4bdda51b416946070e938"}, + {file = "pydantic-1.10.22-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:654322b85642e9439d7de4c83cb4084ddd513df7ff8706005dada43b34544946"}, + {file = "pydantic-1.10.22-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8bece75bd1b9fc1c32b57a32831517943b1159ba18b4ba32c0d431d76a120ae"}, + {file = "pydantic-1.10.22-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eccb58767f13c6963dcf96d02cb8723ebb98b16692030803ac075d2439c07b0f"}, + {file = "pydantic-1.10.22-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7778e6200ff8ed5f7052c1516617423d22517ad36cc7a3aedd51428168e3e5e8"}, + {file = "pydantic-1.10.22-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bffe02767d27c39af9ca7dc7cd479c00dda6346bb62ffc89e306f665108317a2"}, + {file = "pydantic-1.10.22-cp311-cp311-win_amd64.whl", hash = "sha256:23bc19c55427091b8e589bc08f635ab90005f2dc99518f1233386f46462c550a"}, + {file = "pydantic-1.10.22-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:92d0f97828a075a71d9efc65cf75db5f149b4d79a38c89648a63d2932894d8c9"}, + {file = "pydantic-1.10.22-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6af5a2811b6b95b58b829aeac5996d465a5f0c7ed84bd871d603cf8646edf6ff"}, + {file = "pydantic-1.10.22-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6cf06d8d40993e79af0ab2102ef5da77b9ddba51248e4cb27f9f3f591fbb096e"}, + {file = "pydantic-1.10.22-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:184b7865b171a6057ad97f4a17fbac81cec29bd103e996e7add3d16b0d95f609"}, + {file = "pydantic-1.10.22-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:923ad861677ab09d89be35d36111156063a7ebb44322cdb7b49266e1adaba4bb"}, + {file = "pydantic-1.10.22-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:82d9a3da1686443fb854c8d2ab9a473251f8f4cdd11b125522efb4d7c646e7bc"}, + {file = "pydantic-1.10.22-cp312-cp312-win_amd64.whl", hash = "sha256:1612604929af4c602694a7f3338b18039d402eb5ddfbf0db44f1ebfaf07f93e7"}, + {file = "pydantic-1.10.22-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b259dc89c9abcd24bf42f31951fb46c62e904ccf4316393f317abeeecda39978"}, + {file = "pydantic-1.10.22-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9238aa0964d80c0908d2f385e981add58faead4412ca80ef0fa352094c24e46d"}, + {file = "pydantic-1.10.22-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f8029f05b04080e3f1a550575a1bca747c0ea4be48e2d551473d47fd768fc1b"}, + {file = "pydantic-1.10.22-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5c06918894f119e0431a36c9393bc7cceeb34d1feeb66670ef9b9ca48c073937"}, + {file = "pydantic-1.10.22-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e205311649622ee8fc1ec9089bd2076823797f5cd2c1e3182dc0e12aab835b35"}, + {file = "pydantic-1.10.22-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:815f0a73d5688d6dd0796a7edb9eca7071bfef961a7b33f91e618822ae7345b7"}, + {file = "pydantic-1.10.22-cp313-cp313-win_amd64.whl", hash = "sha256:9dfce71d42a5cde10e78a469e3d986f656afc245ab1b97c7106036f088dd91f8"}, + {file = "pydantic-1.10.22-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3ecaf8177b06aac5d1f442db1288e3b46d9f05f34fd17fdca3ad34105328b61a"}, + {file = "pydantic-1.10.22-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb36c2de9ea74bd7f66b5481dea8032d399affd1cbfbb9bb7ce539437f1fce62"}, + {file = "pydantic-1.10.22-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6b8d14a256be3b8fff9286d76c532f1a7573fbba5f189305b22471c6679854d"}, + {file = "pydantic-1.10.22-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:1c33269e815db4324e71577174c29c7aa30d1bba51340ce6be976f6f3053a4c6"}, + {file = "pydantic-1.10.22-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:8661b3ab2735b2a9ccca2634738534a795f4a10bae3ab28ec0a10c96baa20182"}, + {file = "pydantic-1.10.22-cp37-cp37m-win_amd64.whl", hash = "sha256:22bdd5fe70d4549995981c55b970f59de5c502d5656b2abdfcd0a25be6f3763e"}, + {file = "pydantic-1.10.22-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e3f33d1358aa4bc2795208cc29ff3118aeaad0ea36f0946788cf7cadeccc166b"}, + {file = "pydantic-1.10.22-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:813f079f9cd136cac621f3f9128a4406eb8abd2ad9fdf916a0731d91c6590017"}, + {file = "pydantic-1.10.22-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab618ab8dca6eac7f0755db25f6aba3c22c40e3463f85a1c08dc93092d917704"}, + {file = "pydantic-1.10.22-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d128e1aaa38db88caca920d5822c98fc06516a09a58b6d3d60fa5ea9099b32cc"}, + {file = "pydantic-1.10.22-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:cc97bbc25def7025e55fc9016080773167cda2aad7294e06a37dda04c7d69ece"}, + {file = "pydantic-1.10.22-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0dda5d7157d543b1fa565038cae6e952549d0f90071c839b3740fb77c820fab8"}, + {file = "pydantic-1.10.22-cp38-cp38-win_amd64.whl", hash = "sha256:a093fe44fe518cb445d23119511a71f756f8503139d02fcdd1173f7b76c95ffe"}, + {file = "pydantic-1.10.22-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ec54c89b2568b258bb30d7348ac4d82bec1b58b377fb56a00441e2ac66b24587"}, + {file = "pydantic-1.10.22-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d8f1d1a1532e4f3bcab4e34e8d2197a7def4b67072acd26cfa60e92d75803a48"}, + {file = "pydantic-1.10.22-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ad83ca35508c27eae1005b6b61f369f78aae6d27ead2135ec156a2599910121"}, + {file = "pydantic-1.10.22-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53cdb44b78c420f570ff16b071ea8cd5a477635c6b0efc343c8a91e3029bbf1a"}, + {file = "pydantic-1.10.22-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:16d0a5ae9d98264186ce31acdd7686ec05fd331fab9d68ed777d5cb2d1514e5e"}, + {file = "pydantic-1.10.22-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8aee040e25843f036192b1a1af62117504a209a043aa8db12e190bb86ad7e611"}, + {file = "pydantic-1.10.22-cp39-cp39-win_amd64.whl", hash = "sha256:7f691eec68dbbfca497d3c11b92a3e5987393174cbedf03ec7a4184c35c2def6"}, + {file = "pydantic-1.10.22-py3-none-any.whl", hash = "sha256:343037d608bcbd34df937ac259708bfc83664dadf88afe8516c4f282d7d471a9"}, + {file = "pydantic-1.10.22.tar.gz", hash = "sha256:ee1006cebd43a8e7158fb7190bb8f4e2da9649719bff65d0c287282ec38dec6d"}, ] [package.dependencies] @@ -1084,9 +1140,9 @@ email = ["email-validator (>=1.0.3)"] name = "pydocstyle" version = "6.3.0" description = "Python docstring style checker" -category = "dev" optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"}, {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"}, @@ -1096,15 +1152,15 @@ files = [ snowballstemmer = ">=2.2.0" [package.extras] -toml = ["tomli (>=1.2.3)"] +toml = ["tomli (>=1.2.3) ; python_version < \"3.11\""] [[package]] name = "pyflakes" version = "2.4.0" description = "passive checker of Python programs" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["dev"] files = [ {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, @@ -1112,26 +1168,44 @@ files = [ [[package]] name = "pygments" -version = "2.15.1" +version = "2.19.1" description = "Pygments is a syntax highlighting package written in Python." -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"}, + {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pyjwt" +version = "2.10.1" +description = "JSON Web Token implementation in Python" +optional = false +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"}, - {file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"}, + {file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"}, + {file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"}, ] [package.extras] -plugins = ["importlib-metadata"] +crypto = ["cryptography (>=3.4.0)"] +dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"] +docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] +tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] [[package]] name = "pytest" version = "7.2.0" description = "pytest: simple powerful testing with Python" -category = "dev" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, @@ -1153,9 +1227,9 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2. name = "pytest-asyncio" version = "0.16.0" description = "Pytest support for asyncio." -category = "dev" optional = false python-versions = ">= 3.6" +groups = ["dev"] files = [ {file = "pytest-asyncio-0.16.0.tar.gz", hash = "sha256:7496c5977ce88c34379df64a66459fe395cd05543f0a2f837016e7144391fcfb"}, {file = "pytest_asyncio-0.16.0-py3-none-any.whl", hash = "sha256:5f2a21273c47b331ae6aa5b36087047b4899e40f03f18397c0e65fa5cca54e9b"}, @@ -1171,9 +1245,9 @@ testing = ["coverage", "hypothesis (>=5.7.1)"] name = "pytest-cov" version = "4.0.0" description = "Pytest plugin for measuring coverage." -category = "dev" optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "pytest-cov-4.0.0.tar.gz", hash = "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"}, {file = "pytest_cov-4.0.0-py3-none-any.whl", hash = "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b"}, @@ -1188,61 +1262,74 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale [[package]] name = "pyyaml" -version = "6.0" +version = "6.0.2" description = "YAML parser and emitter for Python" -category = "dev" optional = false -python-versions = ">=3.6" -files = [ - {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, - {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, - {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, - {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, - {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, - {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, - {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, - {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, - {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, - {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, - {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, - {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, - {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, - {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, - {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, - {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, - {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, - {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, + {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, + {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, + {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, + {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, + {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, + {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, + {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, + {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, + {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, + {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, + {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, + {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, + {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, + {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, + {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, ] [[package]] name = "requests" version = "2.31.0" description = "Python HTTP for Humans." -category = "dev" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, @@ -1260,14 +1347,14 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "respx" -version = "0.19.0" +version = "0.20.2" description = "A utility for mocking out the Python HTTPX and HTTP Core libraries." -category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" +groups = ["dev"] files = [ - {file = "respx-0.19.0-py2.py3-none-any.whl", hash = "sha256:1ac1cc99bf892ffd3e33108ae43d71d8309a58ac226965f4bd81ec055600f265"}, - {file = "respx-0.19.0.tar.gz", hash = "sha256:4a09e15803c7450d45303520ec528794c9fd77b05984263bc83b78aabbb39413"}, + {file = "respx-0.20.2-py2.py3-none-any.whl", hash = "sha256:ab8e1cf6da28a5b2dd883ea617f8130f77f676736e6e9e4a25817ad116a172c9"}, + {file = "respx-0.20.2.tar.gz", hash = "sha256:07cf4108b1c88b82010f67d3c831dae33a375c7b436e54d87737c7f9f99be643"}, ] [package.dependencies] @@ -1277,9 +1364,9 @@ httpx = ">=0.21.0" name = "restructuredtext-lint" version = "1.4.0" description = "reStructuredText linter" -category = "dev" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "restructuredtext_lint-1.4.0.tar.gz", hash = "sha256:1b235c0c922341ab6c530390892eb9e92f90b9b75046063e047cacfb0f050c45"}, ] @@ -1288,66 +1375,69 @@ files = [ docutils = ">=0.11,<1.0" [[package]] -name = "rfc3986" -version = "1.5.0" -description = "Validating URI References per RFC 3986" -category = "main" +name = "setuptools" +version = "80.4.0" +description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false -python-versions = "*" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, - {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"}, + {file = "setuptools-80.4.0-py3-none-any.whl", hash = "sha256:6cdc8cb9a7d590b237dbe4493614a9b75d0559b888047c1f67d49ba50fc3edb2"}, + {file = "setuptools-80.4.0.tar.gz", hash = "sha256:5a78f61820bc088c8e4add52932ae6b8cf423da2aff268c23f813cfbb13b4006"}, ] -[package.dependencies] -idna = {version = "*", optional = true, markers = "extra == \"idna2008\""} - [package.extras] -idna2008 = ["idna"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.8.0) ; sys_platform != \"cygwin\""] +core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"] [[package]] name = "smmap" -version = "5.0.0" +version = "5.0.2" description = "A pure Python implementation of a sliding window memory map manager" -category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" +groups = ["dev"] files = [ - {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, - {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, + {file = "smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e"}, + {file = "smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5"}, ] [[package]] name = "sniffio" -version = "1.3.0" +version = "1.3.1" description = "Sniff out which async library your code is running under" -category = "main" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] files = [ - {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, - {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] [[package]] name = "snowballstemmer" -version = "2.2.0" -description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." -category = "dev" +version = "3.0.1" +description = "This package provides 32 stemmers for 30 languages generated from Snowball algorithms." optional = false -python-versions = "*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*" +groups = ["dev"] files = [ - {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, - {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, + {file = "snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064"}, + {file = "snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895"}, ] [[package]] name = "starlette" version = "0.27.0" description = "The little ASGI library that shines." -category = "dev" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"}, {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"}, @@ -1362,38 +1452,38 @@ full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyam [[package]] name = "stevedore" -version = "5.1.0" +version = "5.4.1" description = "Manage dynamic plugins for Python applications" -category = "dev" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "stevedore-5.1.0-py3-none-any.whl", hash = "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d"}, - {file = "stevedore-5.1.0.tar.gz", hash = "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c"}, + {file = "stevedore-5.4.1-py3-none-any.whl", hash = "sha256:d10a31c7b86cba16c1f6e8d15416955fc797052351a56af15e608ad20811fcfe"}, + {file = "stevedore-5.4.1.tar.gz", hash = "sha256:3135b5ae50fe12816ef291baff420acb727fcd356106e3e9cbfa9e5985cd6f4b"}, ] [package.dependencies] -pbr = ">=2.0.0,<2.1.0 || >2.1.0" +pbr = ">=2.0.0" [[package]] name = "tokenize-rt" -version = "5.0.0" +version = "6.1.0" description = "A wrapper around the stdlib `tokenize` which roundtrips." -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "tokenize_rt-5.0.0-py2.py3-none-any.whl", hash = "sha256:c67772c662c6b3dc65edf66808577968fb10badfc2042e3027196bed4daf9e5a"}, - {file = "tokenize_rt-5.0.0.tar.gz", hash = "sha256:3160bc0c3e8491312d0485171dea861fc160a240f5f5766b72a1165408d10740"}, + {file = "tokenize_rt-6.1.0-py2.py3-none-any.whl", hash = "sha256:d706141cdec4aa5f358945abe36b911b8cbdc844545da99e811250c0cee9b6fc"}, + {file = "tokenize_rt-6.1.0.tar.gz", hash = "sha256:e8ee836616c0877ab7c7b54776d2fefcc3bde714449a206762425ae114b53c86"}, ] [[package]] name = "toml" version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" -category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +groups = ["dev"] files = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, @@ -1401,43 +1491,74 @@ files = [ [[package]] name = "tomli" -version = "2.0.1" +version = "2.2.1" description = "A lil' TOML parser" -category = "dev" optional = false -python-versions = ">=3.7" -files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +python-versions = ">=3.8" +groups = ["dev"] +markers = "python_full_version <= \"3.11.0a6\"" +files = [ + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] [[package]] name = "typing-extensions" -version = "4.6.2" -description = "Backported and Experimental Type Hints for Python 3.7+" -category = "main" +version = "4.13.2" +description = "Backported and Experimental Type Hints for Python 3.8+" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["main", "dev"] files = [ - {file = "typing_extensions-4.6.2-py3-none-any.whl", hash = "sha256:3a8b36f13dd5fdc5d1b16fe317f5668545de77fa0b8e02006381fd49d731ab98"}, - {file = "typing_extensions-4.6.2.tar.gz", hash = "sha256:06006244c70ac8ee83fa8282cb188f697b8db25bc8b4df07be1873c43897060c"}, + {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, + {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, ] [[package]] name = "urllib3" -version = "2.0.2" +version = "2.4.0" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "urllib3-2.0.2-py3-none-any.whl", hash = "sha256:d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"}, - {file = "urllib3-2.0.2.tar.gz", hash = "sha256:61717a1095d7e155cdb737ac7bb2f4324a858a1e2e6466f6d03ff630ca68d3cc"}, + {file = "urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813"}, + {file = "urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] +h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] @@ -1445,9 +1566,9 @@ zstd = ["zstandard (>=0.18.0)"] name = "uvicorn" version = "0.16.0" description = "The lightning-fast ASGI server." -category = "dev" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "uvicorn-0.16.0-py3-none-any.whl", hash = "sha256:d8c839231f270adaa6d338d525e2652a0b4a5f4c2430b5c4ef6ae4d11776b0d2"}, {file = "uvicorn-0.16.0.tar.gz", hash = "sha256:eacb66afa65e0648fcbce5e746b135d09722231ffffc61883d4fac2b62fbea8d"}, @@ -1459,15 +1580,15 @@ click = ">=7.0" h11 = ">=0.8" [package.extras] -standard = ["PyYAML (>=5.1)", "colorama (>=0.4)", "httptools (>=0.2.0,<0.4.0)", "python-dotenv (>=0.13)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchgod (>=0.6)", "websockets (>=10.0)", "websockets (>=9.1)"] +standard = ["PyYAML (>=5.1)", "colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.2.0,<0.4.0)", "python-dotenv (>=0.13)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1) ; sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"", "watchgod (>=0.6)", "websockets (>=10.0) ; python_version >= \"3.7\"", "websockets (>=9.1) ; python_version < \"3.7\""] [[package]] name = "wemake-python-styleguide" version = "0.16.0" description = "The strictest and most opinionated python linter ever" -category = "dev" optional = false python-versions = ">=3.6,<4.0" +groups = ["dev"] files = [ {file = "wemake-python-styleguide-0.16.0.tar.gz", hash = "sha256:3bf0a4962404e6fd6fa479e72e2ba3fb75d5920ea6c44b72b45240c9e519543c"}, {file = "wemake_python_styleguide-0.16.0-py3-none-any.whl", hash = "sha256:8caa92b4aa77b08a505d718553238812d1b612b1036bc171ca3aa18345efe0b4"}, @@ -1496,20 +1617,21 @@ typing_extensions = ">=3.6,<5.0" [[package]] name = "win32-setctime" -version = "1.1.0" +version = "1.2.0" description = "A small Python utility to set file creation time on Windows" -category = "main" optional = false python-versions = ">=3.5" +groups = ["main"] +markers = "sys_platform == \"win32\"" files = [ - {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"}, - {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"}, + {file = "win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390"}, + {file = "win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0"}, ] [package.extras] -dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] +dev = ["black (>=19.3b0) ; python_version >= \"3.6\"", "pytest (>=4.6.2)"] [metadata] -lock-version = "2.0" -python-versions = ">=3.8,<3.12" -content-hash = "f74561c4a71d30df0ad9ecd6e95ff8390b21cd338745cd436e07f3076911742b" +lock-version = "2.1" +python-versions = ">=3.9,<3.13" +content-hash = "fb06209fa4d2c8171876f51348bb90d77cffd1c4508026b208dfec52c278ab4e" diff --git a/pyproject.toml b/pyproject.toml index cd55818a..c56bdd5d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pybotx" -version = "0.55.5" +version = "0.75.0" description = "A python library for interacting with eXpress BotX API" authors = [ "Sidnev Nikolay ", @@ -9,28 +9,31 @@ authors = [ "Arseniy Zhiltsov " ] readme = "README.md" -documentation = "https://expressapp.github.io/pybotx" repository = "https://github.com/ExpressApp/pybotx" [tool.poetry.dependencies] -python = ">=3.8,<3.12" - -aiofiles = ">=0.7.0,<0.9.0" -httpx = "0.23.0" +python = ">=3.9,<3.13" + +aiofiles = ">=0.7.0,<24.0.0" +httpx = "^0.25.0" +# The v1.0.3 cause some troubles with no-wait callbacks functionality. +# It will be fixed in the next versions. +# https://github.com/encode/httpcore/pull/880 +httpcore = "1.0.9" loguru = ">=0.6.0,<0.7.0" -mypy-extensions = ">=0.2.0,<0.5.0" pydantic = ">=1.6.0,<1.11.0" -typing-extensions = ">=3.7.4,<5.0.0" aiocsv = ">=1.2.3,<1.3.0" +pyjwt = ">=2.0.0,<3.0.0" +mypy-extensions = ">=0.2.0,<0.5.0" - -[tool.poetry.dev-dependencies] +[tool.poetry.group.dev.dependencies] add-trailing-comma = "2.2.1" -autoflake = "1.4.0" +autoflake = "1.7.8" black = "22.3.0" isort = "5.10.1" mypy = "0.910.0" +typing-extensions = ">=3.7.4,<5.0.0" wemake-python-styleguide = "0.16.0" bandit = "1.7.2" # https://github.com/PyCQA/bandit/issues/837 @@ -38,7 +41,7 @@ pytest = "7.2.0" pytest-asyncio = "0.16.0" pytest-cov = "4.0.0" requests = "2.31.0" -respx = "0.19.0" +respx = "0.20.2" fastapi = "0.95.2" starlette = "0.27.0" # TODO: Drop dependency after updating end-to-end test From 920dcf30f639ccded91211660250a5d3c4e544fa Mon Sep 17 00:00:00 2001 From: Aleksandr Osovskii Date: Wed, 14 May 2025 14:54:40 +0300 Subject: [PATCH 03/18] feat: add libs --- poetry.lock | 84 +++++++++++++++++++++++++++++++++++++++++++++++++- pyproject.toml | 2 ++ 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 3ac3d5c2..a11df83d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -454,6 +454,30 @@ files = [ {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"}, ] +[[package]] +name = "deepdiff" +version = "8.5.0" +description = "Deep Difference and Search of any Python object/data. Recreate objects by adding adding deltas to each other." +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "deepdiff-8.5.0-py3-none-any.whl", hash = "sha256:d4599db637f36a1c285f5fdfc2cd8d38bde8d8be8636b65ab5e425b67c54df26"}, + {file = "deepdiff-8.5.0.tar.gz", hash = "sha256:a4dd3529fa8d4cd5b9cbb6e3ea9c95997eaa919ba37dac3966c1b8f872dc1cd1"}, +] + +[package.dependencies] +orderly-set = ">=5.4.1,<6" + +[package.extras] +cli = ["click (>=8.1.0,<8.2.0)", "pyyaml (>=6.0.0,<6.1.0)"] +coverage = ["coverage (>=7.6.0,<7.7.0)"] +dev = ["bump2version (>=1.0.0,<1.1.0)", "ipdb (>=0.13.0,<0.14.0)", "jsonpickle (>=4.0.0,<4.1.0)", "nox (==2025.5.1)", "numpy (>=2.0,<3.0) ; python_version < \"3.10\"", "numpy (>=2.2.0,<2.3.0) ; python_version >= \"3.10\"", "orjson (>=3.10.0,<3.11.0)", "pandas (>=2.2.0,<2.3.0)", "polars (>=1.21.0,<1.22.0)", "python-dateutil (>=2.9.0,<2.10.0)", "tomli (>=2.2.0,<2.3.0)", "tomli-w (>=1.2.0,<1.3.0)"] +docs = ["Sphinx (>=6.2.0,<6.3.0)", "sphinx-sitemap (>=2.6.0,<2.7.0)", "sphinxemoji (>=0.3.0,<0.4.0)"] +optimize = ["orjson"] +static = ["flake8 (>=7.1.0,<7.2.0)", "flake8-pyproject (>=1.2.3,<1.3.0)", "pydantic (>=2.10.0,<2.11.0)"] +test = ["pytest (>=8.3.0,<8.4.0)", "pytest-benchmark (>=5.1.0,<5.2.0)", "pytest-cov (>=6.0.0,<6.1.0)", "python-dotenv (>=1.0.0,<1.1.0)"] + [[package]] name = "docutils" version = "0.21.2" @@ -497,6 +521,40 @@ typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} [package.extras] test = ["pytest (>=6)"] +[[package]] +name = "factory-boy" +version = "3.3.3" +description = "A versatile test fixtures replacement based on thoughtbot's factory_bot for Ruby." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "factory_boy-3.3.3-py2.py3-none-any.whl", hash = "sha256:1c39e3289f7e667c4285433f305f8d506efc2fe9c73aaea4151ebd5cdea394fc"}, + {file = "factory_boy-3.3.3.tar.gz", hash = "sha256:866862d226128dfac7f2b4160287e899daf54f2612778327dd03d0e2cb1e3d03"}, +] + +[package.dependencies] +Faker = ">=0.7.0" + +[package.extras] +dev = ["Django", "Pillow", "SQLAlchemy", "coverage", "flake8", "isort", "mongoengine", "mongomock", "mypy", "tox", "wheel (>=0.32.0)", "zest.releaser[recommended]"] +doc = ["Sphinx", "sphinx-rtd-theme", "sphinxcontrib-spelling"] + +[[package]] +name = "faker" +version = "37.1.0" +description = "Faker is a Python package that generates fake data for you." +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "faker-37.1.0-py3-none-any.whl", hash = "sha256:dc2f730be71cb770e9c715b13374d80dbcee879675121ab51f9683d262ae9a1c"}, + {file = "faker-37.1.0.tar.gz", hash = "sha256:ad9dc66a3b84888b837ca729e85299a96b58fdaef0323ed0baace93c9614af06"}, +] + +[package.dependencies] +tzdata = "*" + [[package]] name = "fastapi" version = "0.95.2" @@ -969,6 +1027,18 @@ files = [ {file = "mypy_extensions-0.4.4.tar.gz", hash = "sha256:c8b707883a96efe9b4bb3aaf0dcc07e7e217d7d8368eec4db4049ee9e142f4fd"}, ] +[[package]] +name = "orderly-set" +version = "5.4.1" +description = "Orderly set" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "orderly_set-5.4.1-py3-none-any.whl", hash = "sha256:b5e21d21680bd9ef456885db800c5cb4f76a03879880c0175e1b077fb166fd83"}, + {file = "orderly_set-5.4.1.tar.gz", hash = "sha256:a1fb5a4fdc5e234e9e8d8e5c1bbdbc4540f4dfe50d12bf17c8bc5dbf1c9c878d"}, +] + [[package]] name = "packaging" version = "25.0" @@ -1544,6 +1614,18 @@ files = [ {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, ] +[[package]] +name = "tzdata" +version = "2025.2" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +groups = ["main"] +files = [ + {file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"}, + {file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"}, +] + [[package]] name = "urllib3" version = "2.4.0" @@ -1634,4 +1716,4 @@ dev = ["black (>=19.3b0) ; python_version >= \"3.6\"", "pytest (>=4.6.2)"] [metadata] lock-version = "2.1" python-versions = ">=3.9,<3.13" -content-hash = "fb06209fa4d2c8171876f51348bb90d77cffd1c4508026b208dfec52c278ab4e" +content-hash = "f1cf24ba9d9c65af6e65c394895eb958fd4295ff04842d76d3e867c5a45ef33d" diff --git a/pyproject.toml b/pyproject.toml index c56bdd5d..99cb1709 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,6 +26,8 @@ pydantic = ">=1.6.0,<1.11.0" aiocsv = ">=1.2.3,<1.3.0" pyjwt = ">=2.0.0,<3.0.0" mypy-extensions = ">=0.2.0,<0.5.0" +factory-boy = "^3.3.3" +deepdiff = "^8.5.0" [tool.poetry.group.dev.dependencies] add-trailing-comma = "2.2.1" From 49f99c95d37e320c25fdaf5ecdfaa9177bf5d1e1 Mon Sep 17 00:00:00 2001 From: Aleksandr Osovskii Date: Wed, 14 May 2025 14:56:35 +0300 Subject: [PATCH 04/18] feat: add python 3.13 --- .github/workflows/python-app.yml | 2 +- poetry.lock | 4 ++-- pyproject.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index f4f88195..14ddae9c 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - python-version: ["3.9", "3.10", "3.11", "3.12"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] steps: - name: Setup dependencies diff --git a/poetry.lock b/poetry.lock index a11df83d..255c37e7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1715,5 +1715,5 @@ dev = ["black (>=19.3b0) ; python_version >= \"3.6\"", "pytest (>=4.6.2)"] [metadata] lock-version = "2.1" -python-versions = ">=3.9,<3.13" -content-hash = "f1cf24ba9d9c65af6e65c394895eb958fd4295ff04842d76d3e867c5a45ef33d" +python-versions = ">=3.9,<=3.13" +content-hash = "0a1db7e84f2d769fe5fcad28b66906b29b42f2aad09ea0c236f9f24ba4f7dc71" diff --git a/pyproject.toml b/pyproject.toml index 99cb1709..655563c4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ repository = "https://github.com/ExpressApp/pybotx" [tool.poetry.dependencies] -python = ">=3.9,<3.13" +python = ">=3.9,<=3.13" aiofiles = ">=0.7.0,<24.0.0" httpx = "^0.25.0" From 1d8c00c9ede87ff15475fa944b3862a174836342 Mon Sep 17 00:00:00 2001 From: Aleksandr Osovskii Date: Wed, 14 May 2025 15:33:58 +0300 Subject: [PATCH 05/18] bump libs --- README.md | 69 +-- poetry.lock | 597 ++++++++++---------- pybotx/async_buffer.py | 19 +- pybotx/bot/callbacks/callback_manager.py | 6 +- pybotx/bot/callbacks/callback_repo_proto.py | 18 +- pybotx/bot/handler_collector.py | 9 +- pybotx/image_validators.py | 2 +- pybotx/models/enums.py | 12 +- pyproject.toml | 48 +- tests/client/test_botx_method.py | 2 +- tests/test_base_command.py | 8 +- tests/test_handler_collector.py | 11 +- 12 files changed, 396 insertions(+), 405 deletions(-) diff --git a/README.md b/README.md index 7bfc0c0a..39673785 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ [![Coverage](https://codecov.io/gh/ExpressApp/pybotx/branch/master/graph/badge.svg)](https://codecov.io/gh/ExpressApp/pybotx/branch/master) [![Code style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black) + ## Особенности * Простая для использования @@ -15,6 +16,7 @@ * Полное покрытие тестами * Полное покрытие аннотациями типов + ## Установка Используя `poetry`: @@ -26,14 +28,15 @@ poetry add pybotx **Предупреждение:** Данный проект находится в активной разработке (`0.y.z`) и его API может быть изменён при повышении минорной версии. + ## Информация о мессенджере eXpress и платформе BotX -[Документация](https://docs.express.ms/) по мессенджеру (включая руководство пользователя и администратора). +Документацию по мессенджеру (включая руководство пользователя и администратора) +можно найти на [официальном сайте](https://express.ms/). Перед тем, как продолжать знакомство с библиотекой `pybotx`, -советуем прочитать данные -статьи: Что -такое [чат-боты](https://docs.express.ms/chatbots/developer-guide/#%D1%87%D0%B0%D1%82-%D0%B1%D0%BE%D1%82-%D0%B8-smartapp) +советуем прочитать данные статьи: Что такое [чат-боты] +(https://docs.express.ms/chatbots/developer-guide/#%D1%87%D0%B0%D1%82-%D0%B1%D0%BE%D1%82-%D0%B8-smartapp) и [SmartApp](https://docs.express.ms/smartapps/developer-guide/) и [Взаимодействие с Bot API и BotX API](https://docs.express.ms/chatbots/developer-guide/api/). В этих статьях находятся исчерпывающие примеры работы с платформой, которые @@ -42,6 +45,7 @@ poetry add pybotx Также не будет лишним ознакомиться с [документацией по плаформе BotX ](https://hackmd.ccsteam.ru/s/botx_platform). + ## Примеры готовых проектов на базе pybotx * [Next Feature Bot](https://github.com/ExpressApp/next-feature-bot) - бот, @@ -51,6 +55,7 @@ poetry add pybotx * [Weather SmartApp](https://github.com/ExpressApp/weather-smartapp) - приложение для просмотра погоды. + ## Минимальный пример бота (интеграция с FastAPI) ```python @@ -145,11 +150,11 @@ async def callback_handler(request: Request) -> JSONResponse: ## Примеры + ### Получение сообщений *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/api/bot-api/command/))* - ```python from uuid import UUID @@ -192,11 +197,11 @@ async def default_handler(_: IncomingMessage, bot: Bot) -> None: print("Hello from default handler") ``` + ### Получение системных событий *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/api/bot-api/command/#%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%BD%D1%8B%D0%B5-%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D1%8B))* - ```python from pybotx import * @@ -215,6 +220,7 @@ async def smartapp_event_handler(event: SmartAppEvent, bot: Bot) -> None: print(f"Got `smartapp_event` event: {event}") ``` + ### Получение синхронных SmartApp событий ```python @@ -226,7 +232,7 @@ collector = HandlerCollector() # Обработчик синхронных Smartapp событий, приходящих на эндпоинт `/smartapps/request` @collector.sync_smartapp_event async def handle_sync_smartapp_event( - event: SmartAppEvent, bot: Bot, + event: SmartAppEvent, bot: Bot, ) -> BotAPISyncSmartAppEventResultResponse: print(f"Got sync smartapp event: {event}") return BotAPISyncSmartAppEventResultResponse.from_domain( @@ -235,6 +241,7 @@ async def handle_sync_smartapp_event( ) ``` + ### Middlewares *(Этот функционал относится исключительно к `pybotx`)* @@ -248,9 +255,9 @@ collector = HandlerCollector() async def custom_api_client_middleware( - message: IncomingMessage, - bot: Bot, - call_next: IncomingMessageHandlerFunc, + message: IncomingMessage, + bot: Bot, + call_next: IncomingMessageHandlerFunc, ) -> None: # До вызова `call_next` (обязателен в каждой миддлвари) располагается # код, который выполняется до того, как сообщение дойдёт до @@ -292,18 +299,18 @@ ADMIN_HUIDS = (UUID("123e4567-e89b-12d3-a456-426614174000"),) async def request_id_middleware( - message: IncomingMessage, - bot: Bot, - call_next: IncomingMessageHandlerFunc, + message: IncomingMessage, + bot: Bot, + call_next: IncomingMessageHandlerFunc, ) -> None: message.state.request_id = uuid4() await call_next(message, bot) async def ensure_admin_middleware( - message: IncomingMessage, - bot: Bot, - call_next: IncomingMessageHandlerFunc, + message: IncomingMessage, + bot: Bot, + call_next: IncomingMessageHandlerFunc, ) -> None: if message.sender.huid not in ADMIN_HUIDS: await bot.answer_message("You are not admin") @@ -327,11 +334,11 @@ admin_collector = HandlerCollector(middlewares=[ensure_admin_middleware]) main_collector.include(admin_collector) ``` + ### Отправка сообщения *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D0%BE%D1%82%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B0-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D1%8F))* - ```python from uuid import UUID @@ -382,11 +389,11 @@ async def prebuild_answer_handler(message: IncomingMessage, bot: Bot) -> None: await bot.send(message=answer) ``` + #### Отправка сообщения с кнопками *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D0%BE%D1%82%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B0-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D1%8F-%D1%81-%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D0%B0%D0%BC%D0%B8))* - ```python from pybotx import * @@ -428,11 +435,11 @@ async def bubbles_handler(message: IncomingMessage, bot: Bot) -> None: ) ``` + #### Упоминание пользователя *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D1%83%D0%BF%D0%BE%D0%BC%D0%B8%D0%BD%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8F))* - ```python from pybotx import * @@ -455,11 +462,11 @@ async def echo_contact_handler(message: IncomingMessage, bot: Bot) -> None: await bot.answer_message(answer) ``` + #### Отправка файла в сообщении *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D0%BE%D1%82%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B0-%D1%84%D0%B0%D0%B9%D0%BB%D0%B0-%D0%B2-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B8))* - ```python from aiofiles.tempfile import NamedTemporaryFile @@ -494,7 +501,6 @@ async def echo_file_handler(message: IncomingMessage, bot: Bot) -> None: *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D1%80%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B9))* - ```python from pybotx import * @@ -533,7 +539,6 @@ async def increment_handler(message: IncomingMessage, bot: Bot) -> None: *([подробное описание функции]( https://hackmd.ccsteam.ru/s/E9MPeOxjP#%D0%A3%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D1%8F))* - ```python from pybotx import * @@ -558,6 +563,7 @@ async def deleted_message_handler(message: IncomingMessage, bot: Bot) -> None: await bot.answer_message("Self-deleted message", bubbles=bubbles) ``` + ### Обработчики ошибок *(Этот функционал относится исключительно к `pybotx`)* @@ -569,9 +575,9 @@ from pybotx import * async def internal_error_handler( - message: IncomingMessage, - bot: Bot, - exc: Exception, + message: IncomingMessage, + bot: Bot, + exc: Exception, ) -> None: logger.exception("Internal error:") @@ -593,7 +599,6 @@ bot = Bot( *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5-%D1%87%D0%B0%D1%82%D0%B0))* - ```python from pybotx import * @@ -625,7 +630,6 @@ async def create_group_chat_handler(message: IncomingMessage, bot: Bot) -> None: *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D0%BF%D0%BE%D0%B8%D1%81%D0%BA-%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8F))* - ```python import dataclasses @@ -652,7 +656,6 @@ async def search_user_handler(message: IncomingMessage, bot: Bot) -> None: *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D0%BF%D0%BE%D0%BB%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D0%BF%D0%B8%D1%81%D0%BA%D0%B0-%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B5%D0%B9-%D0%BD%D0%B0-cts))* - ```python from pybotx import * @@ -662,11 +665,11 @@ collector = HandlerCollector() @collector.command("/get_users_list", description="Get a list of users") async def users_list_handler(message: IncomingMessage, bot: Bot) -> None: async with bot.users_as_csv( - bot_id=message.bot.id, - cts_user=True, - unregistered=False, - botx=False, + bot_id=message.bot.id, + cts_user=True, + unregistered=False, + botx=False, ) as users: async for user in users: print(user) -``` +``` \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 255c37e7..0eb11c13 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,14 +2,14 @@ [[package]] name = "add-trailing-comma" -version = "2.2.1" +version = "3.1.0" description = "Automatically add trailing commas to calls and literals" optional = false -python-versions = ">=3.6.1" +python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "add_trailing_comma-2.2.1-py2.py3-none-any.whl", hash = "sha256:981c18282b38ec5bceab80ef11485440334d2a274fcf3fce1f91692374b6d818"}, - {file = "add_trailing_comma-2.2.1.tar.gz", hash = "sha256:1640e97c4e85132633a6cb19b29e392dbaf9516292388afa685f7ef1012468e0"}, + {file = "add_trailing_comma-3.1.0-py2.py3-none-any.whl", hash = "sha256:160207e2ac414a841a71f4f5095f7350f87af460aab3dfe36cfa037992530e5c"}, + {file = "add_trailing_comma-3.1.0.tar.gz", hash = "sha256:b255319d7ef6dca308b051ffd80fccf98c018879744c7c7e03083b2eee079c45"}, ] [package.dependencies] @@ -85,24 +85,6 @@ doc = ["Sphinx (>=8.2,<9.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", test = ["anyio[trio]", "blockbuster (>=1.5.23)", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\" and python_version < \"3.14\""] trio = ["trio (>=0.26.1)"] -[[package]] -name = "asgiref" -version = "3.8.1" -description = "ASGI specs, helper code, and adapters" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47"}, - {file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"}, -] - -[package.dependencies] -typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""} - -[package.extras] -tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] - [[package]] name = "astor" version = "0.8.1" @@ -137,87 +119,89 @@ tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" a [[package]] name = "autoflake" -version = "1.7.8" +version = "2.3.1" description = "Removes unused imports and unused variables" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "autoflake-1.7.8-py3-none-any.whl", hash = "sha256:46373ef69b6714f5064c923bb28bd797c4f8a9497f557d87fc36665c6d956b39"}, - {file = "autoflake-1.7.8.tar.gz", hash = "sha256:e7e46372dee46fa1c97acf310d99d922b63d369718a270809d7c278d34a194cf"}, + {file = "autoflake-2.3.1-py3-none-any.whl", hash = "sha256:3ae7495db9084b7b32818b4140e6dc4fc280b712fb414f5b8fe57b0a8e85a840"}, + {file = "autoflake-2.3.1.tar.gz", hash = "sha256:c98b75dc5b0a86459c4f01a1d32ac7eb4338ec4317a4469515ff1e687ecd909e"}, ] [package.dependencies] -pyflakes = ">=1.1.0,<3" +pyflakes = ">=3.0.0" tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} [[package]] name = "bandit" -version = "1.7.2" +version = "1.8.3" description = "Security oriented static analyser for python code." optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "bandit-1.7.2-py3-none-any.whl", hash = "sha256:e20402cadfd126d85b68ed4c8862959663c8c372dbbb1fca8f8e2c9f55a067ec"}, - {file = "bandit-1.7.2.tar.gz", hash = "sha256:6d11adea0214a43813887bfe71a377b5a9955e4c826c8ffd341b494e3ab25260"}, + {file = "bandit-1.8.3-py3-none-any.whl", hash = "sha256:28f04dc0d258e1dd0f99dee8eefa13d1cb5e3fde1a5ab0c523971f97b289bcd8"}, + {file = "bandit-1.8.3.tar.gz", hash = "sha256:f5847beb654d309422985c36644649924e0ea4425c76dec2e89110b87506193a"}, ] [package.dependencies] colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} -GitPython = ">=1.0.1" PyYAML = ">=5.3.1" +rich = "*" stevedore = ">=1.20.0" [package.extras] -test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "toml"] -toml = ["toml"] +baseline = ["GitPython (>=3.1.30)"] +sarif = ["jschema-to-python (>=1.2.3)", "sarif-om (>=1.0.4)"] +test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)"] +toml = ["tomli (>=1.1.0) ; python_version < \"3.11\""] yaml = ["PyYAML"] [[package]] name = "black" -version = "22.3.0" +version = "25.1.0" description = "The uncompromising code formatter." optional = false -python-versions = ">=3.6.2" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "black-22.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09"}, - {file = "black-22.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb"}, - {file = "black-22.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a"}, - {file = "black-22.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968"}, - {file = "black-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d"}, - {file = "black-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cc1e1de68c8e5444e8f94c3670bb48a2beef0e91dddfd4fcc29595ebd90bb9ce"}, - {file = "black-22.3.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2fc92002d44746d3e7db7cf9313cf4452f43e9ea77a2c939defce3b10b5c82"}, - {file = "black-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:a6342964b43a99dbc72f72812bf88cad8f0217ae9acb47c0d4f141a6416d2d7b"}, - {file = "black-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:328efc0cc70ccb23429d6be184a15ce613f676bdfc85e5fe8ea2a9354b4e9015"}, - {file = "black-22.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06f9d8846f2340dfac80ceb20200ea5d1b3f181dd0556b47af4e8e0b24fa0a6b"}, - {file = "black-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4efa5fad66b903b4a5f96d91461d90b9507a812b3c5de657d544215bb7877a"}, - {file = "black-22.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8477ec6bbfe0312c128e74644ac8a02ca06bcdb8982d4ee06f209be28cdf163"}, - {file = "black-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:637a4014c63fbf42a692d22b55d8ad6968a946b4a6ebc385c5505d9625b6a464"}, - {file = "black-22.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:863714200ada56cbc366dc9ae5291ceb936573155f8bf8e9de92aef51f3ad0f0"}, - {file = "black-22.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10dbe6e6d2988049b4655b2b739f98785a884d4d6b85bc35133a8fb9a2233176"}, - {file = "black-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:cee3e11161dde1b2a33a904b850b0899e0424cc331b7295f2a9698e79f9a69a0"}, - {file = "black-22.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20"}, - {file = "black-22.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a"}, - {file = "black-22.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad"}, - {file = "black-22.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21"}, - {file = "black-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265"}, - {file = "black-22.3.0-py3-none-any.whl", hash = "sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72"}, - {file = "black-22.3.0.tar.gz", hash = "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79"}, + {file = "black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32"}, + {file = "black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da"}, + {file = "black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7"}, + {file = "black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9"}, + {file = "black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0"}, + {file = "black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299"}, + {file = "black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096"}, + {file = "black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2"}, + {file = "black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b"}, + {file = "black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc"}, + {file = "black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f"}, + {file = "black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba"}, + {file = "black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f"}, + {file = "black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3"}, + {file = "black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171"}, + {file = "black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18"}, + {file = "black-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0"}, + {file = "black-25.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f"}, + {file = "black-25.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e"}, + {file = "black-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355"}, + {file = "black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717"}, + {file = "black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666"}, ] [package.dependencies] click = ">=8.0.0" mypy-extensions = ">=0.4.3" +packaging = ">=22.0" pathspec = ">=0.9.0" platformdirs = ">=2" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} +typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] +d = ["aiohttp (>=3.10)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] @@ -557,93 +541,91 @@ tzdata = "*" [[package]] name = "fastapi" -version = "0.95.2" +version = "0.115.12" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "fastapi-0.95.2-py3-none-any.whl", hash = "sha256:d374dbc4ef2ad9b803899bd3360d34c534adc574546e25314ab72c0c4411749f"}, - {file = "fastapi-0.95.2.tar.gz", hash = "sha256:4d9d3e8c71c73f11874bcf5e33626258d143252e329a01002f767306c64fb982"}, + {file = "fastapi-0.115.12-py3-none-any.whl", hash = "sha256:e94613d6c05e27be7ffebdd6ea5f388112e5e430c8f7d6494a9d1d88d43e814d"}, + {file = "fastapi-0.115.12.tar.gz", hash = "sha256:1e2c2a2646905f9e83d32f04a3f86aff4a286669c6c950ca95b5fd68c2602681"}, ] [package.dependencies] -pydantic = ">=1.6.2,<1.7 || >1.7,<1.7.1 || >1.7.1,<1.7.2 || >1.7.2,<1.7.3 || >1.7.3,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0" -starlette = ">=0.27.0,<0.28.0" +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" +starlette = ">=0.40.0,<0.47.0" +typing-extensions = ">=4.8.0" [package.extras] -all = ["email-validator (>=1.1.1)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "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)"] -dev = ["pre-commit (>=2.17.0,<3.0.0)", "ruff (==0.0.138)", "uvicorn[standard] (>=0.12.0,<0.21.0)"] -doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pyyaml (>=5.3.1,<7.0.0)", "typer-cli (>=0.0.13,<0.0.14)", "typer[all] (>=0.6.1,<0.8.0)"] -test = ["anyio[trio] (>=3.2.1,<4.0.0)", "black (==23.1.0)", "coverage[toml] (>=6.5.0,<8.0)", "databases[sqlite] (>=0.3.2,<0.7.0)", "email-validator (>=1.1.1,<2.0.0)", "flask (>=1.1.2,<3.0.0)", "httpx (>=0.23.0,<0.24.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.982)", "orjson (>=3.2.1,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "peewee (>=3.13.3,<4.0.0)", "pytest (>=7.1.3,<8.0.0)", "python-jose[cryptography] (>=3.3.0,<4.0.0)", "python-multipart (>=0.0.5,<0.0.7)", "pyyaml (>=5.3.1,<7.0.0)", "ruff (==0.0.138)", "sqlalchemy (>=1.3.18,<1.4.43)", "types-orjson (==3.6.2)", "types-ujson (==5.7.0.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)"] +all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=3.1.5)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "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)"] +standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=3.1.5)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"] [[package]] name = "flake8" -version = "4.0.1" +version = "7.2.0" description = "the modular source code checker: pep8 pyflakes and co" optional = false -python-versions = ">=3.6" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, - {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, + {file = "flake8-7.2.0-py2.py3-none-any.whl", hash = "sha256:93b92ba5bdb60754a6da14fa3b93a9361fd00a59632ada61fd7b130436c40343"}, + {file = "flake8-7.2.0.tar.gz", hash = "sha256:fa558ae3f6f7dbf2b4f22663e5343b6b6023620461f8d4ff2019ef4b5ee70426"}, ] [package.dependencies] -mccabe = ">=0.6.0,<0.7.0" -pycodestyle = ">=2.8.0,<2.9.0" -pyflakes = ">=2.4.0,<2.5.0" +mccabe = ">=0.7.0,<0.8.0" +pycodestyle = ">=2.13.0,<2.14.0" +pyflakes = ">=3.3.0,<3.4.0" [[package]] name = "flake8-bandit" -version = "2.1.2" +version = "4.1.1" description = "Automated security testing with bandit and flake8." optional = false -python-versions = "*" +python-versions = ">=3.6" groups = ["dev"] files = [ - {file = "flake8_bandit-2.1.2.tar.gz", hash = "sha256:687fc8da2e4a239b206af2e54a90093572a60d0954f3054e23690739b0b0de3b"}, + {file = "flake8_bandit-4.1.1-py3-none-any.whl", hash = "sha256:4c8a53eb48f23d4ef1e59293657181a3c989d0077c9952717e98a0eace43e06d"}, + {file = "flake8_bandit-4.1.1.tar.gz", hash = "sha256:068e09287189cbfd7f986e92605adea2067630b75380c6b5733dab7d87f9a84e"}, ] [package.dependencies] -bandit = "*" -flake8 = "*" -flake8-polyfill = "*" -pycodestyle = "*" +bandit = ">=1.7.3" +flake8 = ">=5.0.0" [[package]] name = "flake8-broken-line" -version = "0.4.0" +version = "1.0.0" description = "Flake8 plugin to forbid backslashes for line breaks" optional = false -python-versions = ">=3.6,<4.0" +python-versions = ">=3.8,<4.0" groups = ["dev"] files = [ - {file = "flake8-broken-line-0.4.0.tar.gz", hash = "sha256:771aab5aa0997666796fed249d0e48e6c01cdfeca8c95521eea28a38b7ced4c7"}, - {file = "flake8_broken_line-0.4.0-py3-none-any.whl", hash = "sha256:e9c522856862239a2c7ef2c1de0276fa598572aa864bd4e9c7efc2a827538515"}, + {file = "flake8_broken_line-1.0.0-py3-none-any.whl", hash = "sha256:96c964336024a5030dc536a9f6fb02aa679e2d2a6b35b80a558b5136c35832a9"}, + {file = "flake8_broken_line-1.0.0.tar.gz", hash = "sha256:e2c6a17f8d9a129e99c1320fce89b33843e2963871025c4c2bb7b8b8d8732a85"}, ] [package.dependencies] -flake8 = ">=3.5,<5" +flake8 = ">5" [[package]] name = "flake8-bugbear" -version = "21.11.29" +version = "24.12.12" description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." optional = false -python-versions = ">=3.6" +python-versions = ">=3.8.1" groups = ["dev"] files = [ - {file = "flake8-bugbear-21.11.29.tar.gz", hash = "sha256:8b04cb2fafc6a78e1a9d873bd3988e4282f7959bb6b0d7c1ae648ec09b937a7b"}, - {file = "flake8_bugbear-21.11.29-py36.py37.py38-none-any.whl", hash = "sha256:179e41ddae5de5e3c20d1f61736feeb234e70958fbb56ab3c28a67739c8e9a82"}, + {file = "flake8_bugbear-24.12.12-py3-none-any.whl", hash = "sha256:1b6967436f65ca22a42e5373aaa6f2d87966ade9aa38d4baf2a1be550767545e"}, + {file = "flake8_bugbear-24.12.12.tar.gz", hash = "sha256:46273cef0a6b6ff48ca2d69e472f41420a42a46e24b2a8972e4f0d6733d12a64"}, ] [package.dependencies] -attrs = ">=19.2.0" -flake8 = ">=3.0.0" +attrs = ">=22.2.0" +flake8 = ">=6.0.0" [package.extras] -dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit"] +dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "pytest", "tox"] [[package]] name = "flake8-commas" @@ -709,54 +691,39 @@ pydocstyle = ">=2.1" [[package]] name = "flake8-eradicate" -version = "1.4.0" +version = "1.5.0" description = "Flake8 plugin to find commented out code" optional = false -python-versions = ">=3.7,<4.0" +python-versions = ">=3.8,<4.0" groups = ["dev"] files = [ - {file = "flake8-eradicate-1.4.0.tar.gz", hash = "sha256:3088cfd6717d1c9c6c3ac45ef2e5f5b6c7267f7504d5a74b781500e95cb9c7e1"}, - {file = "flake8_eradicate-1.4.0-py3-none-any.whl", hash = "sha256:e3bbd0871be358e908053c1ab728903c114f062ba596b4d40c852fd18f473d56"}, + {file = "flake8_eradicate-1.5.0-py3-none-any.whl", hash = "sha256:18acc922ad7de623f5247c7d5595da068525ec5437dd53b22ec2259b96ce9d22"}, + {file = "flake8_eradicate-1.5.0.tar.gz", hash = "sha256:aee636cb9ecb5594a7cd92d67ad73eb69909e5cc7bd81710cf9d00970f3983a6"}, ] [package.dependencies] attrs = "*" eradicate = ">=2.0,<3.0" -flake8 = ">=3.5,<6" +flake8 = ">5" [[package]] name = "flake8-isort" -version = "4.2.0" -description = "flake8 plugin that integrates isort ." +version = "6.1.2" +description = "flake8 plugin that integrates isort" optional = false -python-versions = "*" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "flake8-isort-4.2.0.tar.gz", hash = "sha256:26571500cd54976bbc0cf1006ffbcd1a68dd102f816b7a1051b219616ba9fee0"}, - {file = "flake8_isort-4.2.0-py3-none-any.whl", hash = "sha256:5b87630fb3719bf4c1833fd11e0d9534f43efdeba524863e15d8f14a7ef6adbf"}, + {file = "flake8_isort-6.1.2-py3-none-any.whl", hash = "sha256:549197dedf0273502fb74f04c080beed9e62a7eb70244610413d27052e78bd3b"}, + {file = "flake8_isort-6.1.2.tar.gz", hash = "sha256:9d0452acdf0e1cd6f2d6848e3605e66b54d920e73471fb4744eef0f93df62d5d"}, ] [package.dependencies] -flake8 = ">=3.2.1,<6" -isort = ">=4.3.5,<6" +flake8 = "*" +isort = ">=5.0.0,<7" [package.extras] -test = ["pytest-cov"] - -[[package]] -name = "flake8-polyfill" -version = "1.0.2" -description = "Polyfill package for Flake8 plugins" -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "flake8-polyfill-1.0.2.tar.gz", hash = "sha256:e44b087597f6da52ec6393a709e7108b2905317d0c0b744cdca6208e670d8eda"}, - {file = "flake8_polyfill-1.0.2-py2.py3-none-any.whl", hash = "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9"}, -] - -[package.dependencies] -flake8 = "*" +test = ["pytest"] [[package]] name = "flake8-quotes" @@ -775,20 +742,23 @@ setuptools = "*" [[package]] name = "flake8-rst-docstrings" -version = "0.2.7" -description = "Python docstring reStructuredText (RST) validator" +version = "0.3.1" +description = "Python docstring reStructuredText (RST) validator for flake8" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "flake8-rst-docstrings-0.2.7.tar.gz", hash = "sha256:2740067ab9237559dd45a3434d8c987792c7b259ca563621a3b95efe201f5382"}, - {file = "flake8_rst_docstrings-0.2.7-py3-none-any.whl", hash = "sha256:5d56075dce360bcc9c6775bfe7cb431aa395de600ca7e8d40580a28d50b2a803"}, + {file = "flake8_rst_docstrings-0.3.1-py3-none-any.whl", hash = "sha256:ed831afca7ee47851e2162d5fa726b823b446fd46085c2164d7979ae5d9a96d7"}, + {file = "flake8_rst_docstrings-0.3.1.tar.gz", hash = "sha256:26dcc1338caf985990677696a8a6a274f73a0c6845b85f567befd3b648db78e2"}, ] [package.dependencies] -flake8 = ">=3.0.0" +flake8 = ">=3" pygments = "*" -restructuredtext-lint = "*" +restructuredtext_lint = "*" + +[package.extras] +develop = ["build", "twine"] [[package]] name = "flake8-string-format" @@ -805,40 +775,6 @@ files = [ [package.dependencies] flake8 = "*" -[[package]] -name = "gitdb" -version = "4.0.12" -description = "Git Object Database" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf"}, - {file = "gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571"}, -] - -[package.dependencies] -smmap = ">=3.0.1,<6" - -[[package]] -name = "gitpython" -version = "3.1.44" -description = "GitPython is a Python library used to interact with Git repositories" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "GitPython-3.1.44-py3-none-any.whl", hash = "sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110"}, - {file = "gitpython-3.1.44.tar.gz", hash = "sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269"}, -] - -[package.dependencies] -gitdb = ">=4.0.1,<5" - -[package.extras] -doc = ["sphinx (>=7.1.2,<7.2)", "sphinx-autodoc-typehints", "sphinx_rtd_theme"] -test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock ; python_version < \"3.8\"", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions ; python_version < \"3.11\""] - [[package]] name = "h11" version = "0.16.0" @@ -875,14 +811,14 @@ trio = ["trio (>=0.22.0,<1.0)"] [[package]] name = "httpx" -version = "0.25.2" +version = "0.28.1" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" groups = ["main", "dev"] files = [ - {file = "httpx-0.25.2-py3-none-any.whl", hash = "sha256:a05d3d052d9b2dfce0e3896636467f8a5342fb2b902c819428e1ac65413ca118"}, - {file = "httpx-0.25.2.tar.gz", hash = "sha256:8b8fcaa0c8ea7b05edd69a094e63a2094c4efcb48129fb757361bc423c0ad9e8"}, + {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, + {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, ] [package.dependencies] @@ -890,13 +826,13 @@ anyio = "*" certifi = "*" httpcore = "==1.*" idna = "*" -sniffio = "*" [package.extras] brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] +zstd = ["zstandard (>=0.18.0)"] [[package]] name = "idna" @@ -927,21 +863,19 @@ files = [ [[package]] name = "isort" -version = "5.10.1" +version = "6.0.1" description = "A Python utility / library to sort Python imports." optional = false -python-versions = ">=3.6.1,<4.0" +python-versions = ">=3.9.0" groups = ["dev"] files = [ - {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, - {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, + {file = "isort-6.0.1-py3-none-any.whl", hash = "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615"}, + {file = "isort-6.0.1.tar.gz", hash = "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450"}, ] [package.extras] -colors = ["colorama (>=0.4.3,<0.5.0)"] -pipfile-deprecated-finder = ["pipreqs", "requirementslib"] +colors = ["colorama"] plugins = ["setuptools"] -requirements-deprecated-finder = ["pip-api", "pipreqs"] [[package]] name = "loguru" @@ -962,69 +896,119 @@ win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} [package.extras] dev = ["Sphinx (>=4.1.1) ; python_version >= \"3.6\"", "black (>=19.10b0) ; python_version >= \"3.6\"", "colorama (>=0.3.4)", "docutils (==0.16)", "flake8 (>=3.7.7)", "isort (>=5.1.1) ; python_version >= \"3.6\"", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "sphinx-autobuild (>=0.7.1) ; python_version >= \"3.6\"", "sphinx-rtd-theme (>=0.4.3) ; python_version >= \"3.6\"", "tox (>=3.9.0)"] +[[package]] +name = "markdown-it-py" +version = "3.0.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, +] + +[package.dependencies] +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins"] +profiling = ["gprof2dot"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + [[package]] name = "mccabe" -version = "0.6.1" +version = "0.7.0" description = "McCabe checker, plugin for flake8" optional = false -python-versions = "*" +python-versions = ">=3.6" +groups = ["dev"] +files = [ + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +optional = false +python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, - {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, ] [[package]] name = "mypy" -version = "0.910" +version = "1.15.0" description = "Optional static typing for Python" optional = false -python-versions = ">=3.5" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "mypy-0.910-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:a155d80ea6cee511a3694b108c4494a39f42de11ee4e61e72bc424c490e46457"}, - {file = "mypy-0.910-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b94e4b785e304a04ea0828759172a15add27088520dc7e49ceade7834275bedb"}, - {file = "mypy-0.910-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:088cd9c7904b4ad80bec811053272986611b84221835e079be5bcad029e79dd9"}, - {file = "mypy-0.910-cp35-cp35m-win_amd64.whl", hash = "sha256:adaeee09bfde366d2c13fe6093a7df5df83c9a2ba98638c7d76b010694db760e"}, - {file = "mypy-0.910-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ecd2c3fe726758037234c93df7e98deb257fd15c24c9180dacf1ef829da5f921"}, - {file = "mypy-0.910-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d9dd839eb0dc1bbe866a288ba3c1afc33a202015d2ad83b31e875b5905a079b6"}, - {file = "mypy-0.910-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:3e382b29f8e0ccf19a2df2b29a167591245df90c0b5a2542249873b5c1d78212"}, - {file = "mypy-0.910-cp36-cp36m-win_amd64.whl", hash = "sha256:53fd2eb27a8ee2892614370896956af2ff61254c275aaee4c230ae771cadd885"}, - {file = "mypy-0.910-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b6fb13123aeef4a3abbcfd7e71773ff3ff1526a7d3dc538f3929a49b42be03f0"}, - {file = "mypy-0.910-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e4dab234478e3bd3ce83bac4193b2ecd9cf94e720ddd95ce69840273bf44f6de"}, - {file = "mypy-0.910-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:7df1ead20c81371ccd6091fa3e2878559b5c4d4caadaf1a484cf88d93ca06703"}, - {file = "mypy-0.910-cp37-cp37m-win_amd64.whl", hash = "sha256:0aadfb2d3935988ec3815952e44058a3100499f5be5b28c34ac9d79f002a4a9a"}, - {file = "mypy-0.910-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ec4e0cd079db280b6bdabdc807047ff3e199f334050db5cbb91ba3e959a67504"}, - {file = "mypy-0.910-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:119bed3832d961f3a880787bf621634ba042cb8dc850a7429f643508eeac97b9"}, - {file = "mypy-0.910-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:866c41f28cee548475f146aa4d39a51cf3b6a84246969f3759cb3e9c742fc072"}, - {file = "mypy-0.910-cp38-cp38-win_amd64.whl", hash = "sha256:ceb6e0a6e27fb364fb3853389607cf7eb3a126ad335790fa1e14ed02fba50811"}, - {file = "mypy-0.910-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a85e280d4d217150ce8cb1a6dddffd14e753a4e0c3cf90baabb32cefa41b59e"}, - {file = "mypy-0.910-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:42c266ced41b65ed40a282c575705325fa7991af370036d3f134518336636f5b"}, - {file = "mypy-0.910-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:3c4b8ca36877fc75339253721f69603a9c7fdb5d4d5a95a1a1b899d8b86a4de2"}, - {file = "mypy-0.910-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:c0df2d30ed496a08de5daed2a9ea807d07c21ae0ab23acf541ab88c24b26ab97"}, - {file = "mypy-0.910-cp39-cp39-win_amd64.whl", hash = "sha256:c6c2602dffb74867498f86e6129fd52a2770c48b7cd3ece77ada4fa38f94eba8"}, - {file = "mypy-0.910-py3-none-any.whl", hash = "sha256:ef565033fa5a958e62796867b1df10c40263ea9ded87164d67572834e57a174d"}, - {file = "mypy-0.910.tar.gz", hash = "sha256:704098302473cb31a218f1775a873b376b30b4c18229421e9e9dc8916fd16150"}, + {file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, + {file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, + {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"}, + {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"}, + {file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"}, + {file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"}, + {file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}, + {file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}, + {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}, + {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}, + {file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}, + {file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}, + {file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"}, + {file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"}, + {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"}, + {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}, + {file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}, + {file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}, + {file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"}, + {file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"}, + {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"}, + {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"}, + {file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"}, + {file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"}, + {file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"}, + {file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"}, + {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"}, + {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"}, + {file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"}, + {file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"}, + {file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}, + {file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"}, ] [package.dependencies] -mypy-extensions = ">=0.4.3,<0.5.0" -toml = "*" -typing-extensions = ">=3.7.4" +mypy_extensions = ">=1.0.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing_extensions = ">=4.6.0" [package.extras] dmypy = ["psutil (>=4.0)"] -python2 = ["typed-ast (>=1.4.0,<1.5.0)"] +faster-cache = ["orjson"] +install-types = ["pip"] +mypyc = ["setuptools (>=50)"] +reports = ["lxml"] [[package]] name = "mypy-extensions" -version = "0.4.4" -description = "Experimental type system extensions for programs checked with the mypy typechecker." +version = "1.1.0" +description = "Type system extensions for programs checked with the mypy type checker." optional = false -python-versions = ">=2.7" +python-versions = ">=3.8" groups = ["main", "dev"] files = [ - {file = "mypy_extensions-0.4.4.tar.gz", hash = "sha256:c8b707883a96efe9b4bb3aaf0dcc07e7e217d7d8368eec4db4049ee9e142f4fd"}, + {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, + {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, ] [[package]] @@ -1080,19 +1064,18 @@ setuptools = "*" [[package]] name = "pep8-naming" -version = "0.12.1" +version = "0.13.3" description = "Check PEP-8 naming conventions, plugin for flake8" optional = false -python-versions = "*" +python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "pep8-naming-0.12.1.tar.gz", hash = "sha256:bb2455947757d162aa4cad55dba4ce029005cd1692f2899a21d51d8630ca7841"}, - {file = "pep8_naming-0.12.1-py2.py3-none-any.whl", hash = "sha256:4a8daeaeb33cfcde779309fc0c9c0a68a3bbe2ad8a8308b763c5068f86eb9f37"}, + {file = "pep8-naming-0.13.3.tar.gz", hash = "sha256:1705f046dfcd851378aac3be1cd1551c7c1e5ff363bacad707d43007877fa971"}, + {file = "pep8_naming-0.13.3-py3-none-any.whl", hash = "sha256:1a86b8c71a03337c97181917e2b472f0f5e4ccb06844a0d6f0a33522549e7a80"}, ] [package.dependencies] -flake8 = ">=3.9.1" -flake8-polyfill = ">=1.0.2,<2" +flake8 = ">=5.0.0" [[package]] name = "platformdirs" @@ -1129,14 +1112,14 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pycodestyle" -version = "2.8.0" +version = "2.13.0" description = "Python style guide checker" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, - {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, + {file = "pycodestyle-2.13.0-py2.py3-none-any.whl", hash = "sha256:35863c5974a271c7a726ed228a14a4f6daf49df369d8c50cd9a6f58a5e143ba9"}, + {file = "pycodestyle-2.13.0.tar.gz", hash = "sha256:c8415bf09abe81d9c7f872502a6eee881fbe85d8763dd5b9924bb0a01d67efae"}, ] [[package]] @@ -1226,14 +1209,14 @@ toml = ["tomli (>=1.2.3) ; python_version < \"3.11\""] [[package]] name = "pyflakes" -version = "2.4.0" +version = "3.3.2" description = "passive checker of Python programs" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, - {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, + {file = "pyflakes-3.3.2-py2.py3-none-any.whl", hash = "sha256:5039c8339cbb1944045f4ee5466908906180f13cc99cc9949348d10f82a5c32a"}, + {file = "pyflakes-3.3.2.tar.gz", hash = "sha256:6dfd61d87b97fba5dcfaaf781171ac16be16453be6d816147989e7f6e6a9576b"}, ] [[package]] @@ -1271,64 +1254,65 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] [[package]] name = "pytest" -version = "7.2.0" +version = "8.3.5" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, - {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, + {file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"}, + {file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"}, ] [package.dependencies] -attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=0.12,<2.0" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} +pluggy = ">=1.5,<2" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-asyncio" -version = "0.16.0" -description = "Pytest support for asyncio." +version = "0.26.0" +description = "Pytest support for asyncio" optional = false -python-versions = ">= 3.6" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "pytest-asyncio-0.16.0.tar.gz", hash = "sha256:7496c5977ce88c34379df64a66459fe395cd05543f0a2f837016e7144391fcfb"}, - {file = "pytest_asyncio-0.16.0-py3-none-any.whl", hash = "sha256:5f2a21273c47b331ae6aa5b36087047b4899e40f03f18397c0e65fa5cca54e9b"}, + {file = "pytest_asyncio-0.26.0-py3-none-any.whl", hash = "sha256:7b51ed894f4fbea1340262bdae5135797ebbe21d8638978e35d31c6d19f72fb0"}, + {file = "pytest_asyncio-0.26.0.tar.gz", hash = "sha256:c4df2a697648241ff39e7f0e4a73050b03f123f760673956cf0d72a4990e312f"}, ] [package.dependencies] -pytest = ">=5.4.0" +pytest = ">=8.2,<9" +typing-extensions = {version = ">=4.12", markers = "python_version < \"3.10\""} [package.extras] -testing = ["coverage", "hypothesis (>=5.7.1)"] +docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1)"] +testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] [[package]] name = "pytest-cov" -version = "4.0.0" +version = "6.1.1" description = "Pytest plugin for measuring coverage." optional = false -python-versions = ">=3.6" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "pytest-cov-4.0.0.tar.gz", hash = "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"}, - {file = "pytest_cov-4.0.0-py3-none-any.whl", hash = "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b"}, + {file = "pytest_cov-6.1.1-py3-none-any.whl", hash = "sha256:bddf29ed2d0ab6f4df17b4c55b0a657287db8684af9c42ea546b21b1041b3dde"}, + {file = "pytest_cov-6.1.1.tar.gz", hash = "sha256:46935f7aaefba760e716c2ebfbe1c216240b9592966e7da99ea8292d4d3e2a0a"}, ] [package.dependencies] -coverage = {version = ">=5.2.1", extras = ["toml"]} +coverage = {version = ">=7.5", extras = ["toml"]} pytest = ">=4.6" [package.extras] -testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] [[package]] name = "pyyaml" @@ -1395,14 +1379,14 @@ files = [ [[package]] name = "requests" -version = "2.31.0" +version = "2.32.3" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -1417,18 +1401,18 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "respx" -version = "0.20.2" +version = "0.22.0" description = "A utility for mocking out the Python HTTPX and HTTP Core libraries." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "respx-0.20.2-py2.py3-none-any.whl", hash = "sha256:ab8e1cf6da28a5b2dd883ea617f8130f77f676736e6e9e4a25817ad116a172c9"}, - {file = "respx-0.20.2.tar.gz", hash = "sha256:07cf4108b1c88b82010f67d3c831dae33a375c7b436e54d87737c7f9f99be643"}, + {file = "respx-0.22.0-py2.py3-none-any.whl", hash = "sha256:631128d4c9aba15e56903fb5f66fb1eff412ce28dd387ca3a81339e52dbd3ad0"}, + {file = "respx-0.22.0.tar.gz", hash = "sha256:3c8924caa2a50bd71aefc07aa812f2466ff489f1848c96e954a5362d17095d91"}, ] [package.dependencies] -httpx = ">=0.21.0" +httpx = ">=0.25.0" [[package]] name = "restructuredtext-lint" @@ -1444,6 +1428,26 @@ files = [ [package.dependencies] docutils = ">=0.11,<1.0" +[[package]] +name = "rich" +version = "14.0.0" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +optional = false +python-versions = ">=3.8.0" +groups = ["dev"] +files = [ + {file = "rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0"}, + {file = "rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725"}, +] + +[package.dependencies] +markdown-it-py = ">=2.2.0" +pygments = ">=2.13.0,<3.0.0" +typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.11\""} + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<9)"] + [[package]] name = "setuptools" version = "80.4.0" @@ -1465,18 +1469,6 @@ enabler = ["pytest-enabler (>=2.2)"] test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"] -[[package]] -name = "smmap" -version = "5.0.2" -description = "A pure Python implementation of a sliding window memory map manager" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e"}, - {file = "smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5"}, -] - [[package]] name = "sniffio" version = "1.3.1" @@ -1503,22 +1495,22 @@ files = [ [[package]] name = "starlette" -version = "0.27.0" +version = "0.46.2" description = "The little ASGI library that shines." optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"}, - {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"}, + {file = "starlette-0.46.2-py3-none-any.whl", hash = "sha256:595633ce89f8ffa71a015caed34a5b2dc1c0cdb3f0f1fbd1e69339cf2abeec35"}, + {file = "starlette-0.46.2.tar.gz", hash = "sha256:7f7361f34eed179294600af672f565727419830b54b7b084efe44bb82d2fccd5"}, ] [package.dependencies] -anyio = ">=3.4.0,<5" +anyio = ">=3.6.2,<5" typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} [package.extras] -full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"] +full = ["httpx (>=0.27.0,<0.29.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.18)", "pyyaml"] [[package]] name = "stevedore" @@ -1547,18 +1539,6 @@ files = [ {file = "tokenize_rt-6.1.0.tar.gz", hash = "sha256:e8ee836616c0877ab7c7b54776d2fefcc3bde714449a206762425ae114b53c86"}, ] -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -groups = ["dev"] -files = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] - [[package]] name = "tomli" version = "2.2.1" @@ -1646,56 +1626,57 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "uvicorn" -version = "0.16.0" +version = "0.34.2" description = "The lightning-fast ASGI server." optional = false -python-versions = "*" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "uvicorn-0.16.0-py3-none-any.whl", hash = "sha256:d8c839231f270adaa6d338d525e2652a0b4a5f4c2430b5c4ef6ae4d11776b0d2"}, - {file = "uvicorn-0.16.0.tar.gz", hash = "sha256:eacb66afa65e0648fcbce5e746b135d09722231ffffc61883d4fac2b62fbea8d"}, + {file = "uvicorn-0.34.2-py3-none-any.whl", hash = "sha256:deb49af569084536d269fe0a6d67e3754f104cf03aba7c11c40f01aadf33c403"}, + {file = "uvicorn-0.34.2.tar.gz", hash = "sha256:0e929828f6186353a80b58ea719861d2629d766293b6d19baf086ba31d4f3328"}, ] [package.dependencies] -asgiref = ">=3.4.0" click = ">=7.0" h11 = ">=0.8" +typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} [package.extras] -standard = ["PyYAML (>=5.1)", "colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.2.0,<0.4.0)", "python-dotenv (>=0.13)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1) ; sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"", "watchgod (>=0.6)", "websockets (>=10.0) ; python_version >= \"3.7\"", "websockets (>=9.1) ; python_version < \"3.7\""] +standard = ["colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1) ; sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"", "watchfiles (>=0.13)", "websockets (>=10.4)"] [[package]] name = "wemake-python-styleguide" -version = "0.16.0" +version = "0.19.2" description = "The strictest and most opinionated python linter ever" optional = false -python-versions = ">=3.6,<4.0" +python-versions = "<4.0,>=3.9" groups = ["dev"] files = [ - {file = "wemake-python-styleguide-0.16.0.tar.gz", hash = "sha256:3bf0a4962404e6fd6fa479e72e2ba3fb75d5920ea6c44b72b45240c9e519543c"}, - {file = "wemake_python_styleguide-0.16.0-py3-none-any.whl", hash = "sha256:8caa92b4aa77b08a505d718553238812d1b612b1036bc171ca3aa18345efe0b4"}, + {file = "wemake_python_styleguide-0.19.2-py3-none-any.whl", hash = "sha256:d53205dbb629755026d853d15fb3ca03ebb2717c97de4198b5676b9bdc0663bd"}, + {file = "wemake_python_styleguide-0.19.2.tar.gz", hash = "sha256:850fe70e6d525fd37ac51778e552a121a489f1bd057184de96ffd74a09aef414"}, ] [package.dependencies] astor = ">=0.8,<0.9" attrs = "*" darglint = ">=1.2,<2.0" -flake8 = ">=3.7,<5" -flake8-bandit = ">=2.1,<3.0" -flake8-broken-line = ">=0.3,<0.5" -flake8-bugbear = ">=20.1,<22.0" +flake8 = ">=7.0,<8.0" +flake8-bandit = ">=4.1,<5.0" +flake8-broken-line = ">=1.0,<2.0" +flake8-bugbear = ">=24.2,<25.0" flake8-commas = ">=2.0,<3.0" flake8-comprehensions = ">=3.1,<4.0" flake8-debugger = ">=4.0,<5.0" flake8-docstrings = ">=1.3,<2.0" -flake8-eradicate = ">=1.0,<2.0" -flake8-isort = ">=4.0,<5.0" +flake8-eradicate = ">=1.5,<2.0" +flake8-isort = ">=6.0,<7.0" flake8-quotes = ">=3.0,<4.0" -flake8-rst-docstrings = ">=0.2.3,<0.3.0" +flake8-rst-docstrings = ">=0.3,<0.4" flake8-string-format = ">=0.3,<0.4" -pep8-naming = ">=0.11,<0.13" +pep8-naming = ">=0.13,<0.14" pygments = ">=2.4,<3.0" -typing_extensions = ">=3.6,<5.0" +setuptools = "*" +typing_extensions = ">=4.0,<5.0" [[package]] name = "win32-setctime" @@ -1716,4 +1697,4 @@ dev = ["black (>=19.3b0) ; python_version >= \"3.6\"", "pytest (>=4.6.2)"] [metadata] lock-version = "2.1" python-versions = ">=3.9,<=3.13" -content-hash = "0a1db7e84f2d769fe5fcad28b66906b29b42f2aad09ea0c236f9f24ba4f7dc71" +content-hash = "bda0e2f3b1e038d1b1202f08d50c91f704faa8206a2d035e6789b013ae50534c" diff --git a/pybotx/async_buffer.py b/pybotx/async_buffer.py index d5e8a8a5..141d8080 100644 --- a/pybotx/async_buffer.py +++ b/pybotx/async_buffer.py @@ -8,21 +8,24 @@ class AsyncBufferBase(Protocol): - async def seek(self, cursor: int, whence: int = os.SEEK_SET) -> int: - ... # noqa: WPS428 + async def seek( + self, + cursor: int, + whence: int = os.SEEK_SET, + ) -> int: ... # noqa: WPS428 - async def tell(self) -> int: - ... # noqa: WPS428 + async def tell(self) -> int: ... # noqa: WPS428 class AsyncBufferWritable(AsyncBufferBase): - async def write(self, content: bytes) -> int: - ... # noqa: WPS428 + async def write(self, content: bytes) -> int: ... # noqa: WPS428 class AsyncBufferReadable(AsyncBufferBase): - async def read(self, bytes_to_read: Optional[int] = None) -> bytes: - ... # noqa: WPS428 + async def read( + self, + bytes_to_read: Optional[int] = None, + ) -> bytes: ... # noqa: WPS428 async def get_file_size(async_buffer: AsyncBufferReadable) -> int: diff --git a/pybotx/bot/callbacks/callback_manager.py b/pybotx/bot/callbacks/callback_manager.py index 76568f23..e9145fe3 100644 --- a/pybotx/bot/callbacks/callback_manager.py +++ b/pybotx/bot/callbacks/callback_manager.py @@ -69,16 +69,14 @@ def setup_callback_timeout_alarm(self, sync_id: UUID, timeout: float) -> None: def cancel_callback_timeout_alarm( self, sync_id: UUID, - ) -> None: - ... # noqa: WPS428 + ) -> None: ... # noqa: WPS428 @overload def cancel_callback_timeout_alarm( self, sync_id: UUID, return_remaining_time: Literal[True], - ) -> float: - ... # noqa: WPS428 + ) -> float: ... # noqa: WPS428 def cancel_callback_timeout_alarm( self, diff --git a/pybotx/bot/callbacks/callback_repo_proto.py b/pybotx/bot/callbacks/callback_repo_proto.py index 3ef262f5..26a3d2a4 100644 --- a/pybotx/bot/callbacks/callback_repo_proto.py +++ b/pybotx/bot/callbacks/callback_repo_proto.py @@ -13,27 +13,25 @@ class CallbackRepoProto(Protocol): - async def create_botx_method_callback(self, sync_id: UUID) -> None: - ... # noqa: WPS428 + async def create_botx_method_callback( + self, + sync_id: UUID, + ) -> None: ... # noqa: WPS428 async def set_botx_method_callback_result( self, callback: BotXMethodCallback, - ) -> None: - ... # noqa: WPS428 + ) -> None: ... # noqa: WPS428 async def wait_botx_method_callback( self, sync_id: UUID, timeout: float, - ) -> BotXMethodCallback: - ... # noqa: WPS428 + ) -> BotXMethodCallback: ... # noqa: WPS428 async def pop_botx_method_callback( self, sync_id: UUID, - ) -> "Future[BotXMethodCallback]": - ... # noqa: WPS428 + ) -> "Future[BotXMethodCallback]": ... # noqa: WPS428 - async def stop_callbacks_waiting(self) -> None: - ... # noqa: WPS428 + async def stop_callbacks_waiting(self) -> None: ... # noqa: WPS428 diff --git a/pybotx/bot/handler_collector.py b/pybotx/bot/handler_collector.py index af05836e..35599f5a 100644 --- a/pybotx/bot/handler_collector.py +++ b/pybotx/bot/handler_collector.py @@ -194,16 +194,17 @@ def decorator( def default_message_handler( self, handler_func: IncomingMessageHandlerFunc, - ) -> IncomingMessageHandlerFunc: - ... # noqa: WPS428 + ) -> IncomingMessageHandlerFunc: ... # noqa: WPS428 @overload def default_message_handler( self, *, middlewares: Optional[Sequence[Middleware]] = None, - ) -> Callable[[IncomingMessageHandlerFunc], IncomingMessageHandlerFunc]: - ... # noqa: WPS428 + ) -> Callable[ + [IncomingMessageHandlerFunc], + IncomingMessageHandlerFunc, + ]: ... # noqa: WPS428 def default_message_handler( # noqa: WPS320 self, diff --git a/pybotx/image_validators.py b/pybotx/image_validators.py index 6f8c4f4c..0a72c288 100644 --- a/pybotx/image_validators.py +++ b/pybotx/image_validators.py @@ -1,7 +1,7 @@ from pybotx.async_buffer import AsyncBufferReadable, get_file_size from pybotx.constants import STICKER_IMAGE_MAX_SIZE -PNG_MAGIC_BYTES: bytes = b"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A" +PNG_MAGIC_BYTES: bytes = b"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a" async def ensure_file_content_is_png(async_buffer: AsyncBufferReadable) -> None: diff --git a/pybotx/models/enums.py b/pybotx/models/enums.py index abb124d2..0f4d06f1 100644 --- a/pybotx/models/enums.py +++ b/pybotx/models/enums.py @@ -307,13 +307,11 @@ def convert_chat_type_from_domain(chat_type: ChatTypes) -> APIChatTypes: @overload def convert_chat_type_to_domain( chat_type: APIChatTypes, -) -> ChatTypes: - ... # noqa: WPS428 +) -> ChatTypes: ... # noqa: WPS428 @overload -def convert_chat_type_to_domain(chat_type: str) -> UNSUPPORTED: - ... # noqa: WPS428 +def convert_chat_type_to_domain(chat_type: str) -> UNSUPPORTED: ... # noqa: WPS428 def convert_chat_type_to_domain( @@ -340,15 +338,13 @@ def convert_chat_type_to_domain( @overload def convert_sync_source_type_to_domain( sync_type: APISyncSourceTypes, -) -> SyncSourceTypes: - ... # noqa: WPS428 +) -> SyncSourceTypes: ... # noqa: WPS428 @overload def convert_sync_source_type_to_domain( sync_type: str, -) -> UNSUPPORTED: - ... # noqa: WPS428 +) -> UNSUPPORTED: ... # noqa: WPS428 def convert_sync_source_type_to_domain( diff --git a/pyproject.toml b/pyproject.toml index 655563c4..13f6f6b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,40 +15,44 @@ repository = "https://github.com/ExpressApp/pybotx" [tool.poetry.dependencies] python = ">=3.9,<=3.13" -aiofiles = ">=0.7.0,<24.0.0" -httpx = "^0.25.0" +aiofiles = ">=0.7.0,<=24.1.0" +httpx = "^0.28.0" # The v1.0.3 cause some troubles with no-wait callbacks functionality. # It will be fixed in the next versions. # https://github.com/encode/httpcore/pull/880 httpcore = "1.0.9" loguru = ">=0.6.0,<0.7.0" pydantic = ">=1.6.0,<1.11.0" -aiocsv = ">=1.2.3,<1.3.0" +aiocsv = ">=1.2.3,<=1.4.0" pyjwt = ">=2.0.0,<3.0.0" -mypy-extensions = ">=0.2.0,<0.5.0" -factory-boy = "^3.3.3" -deepdiff = "^8.5.0" +mypy-extensions = ">=0.2.0,<=1.1.0" +factory-boy = ">=3.3.3,<=4.0.0" +deepdiff = "^8.5.0,<=9.0.0" [tool.poetry.group.dev.dependencies] -add-trailing-comma = "2.2.1" -autoflake = "1.7.8" -black = "22.3.0" -isort = "5.10.1" -mypy = "0.910.0" +add-trailing-comma = "3.1.0" +autoflake = "2.3.1" +black = "25.1.0" +isort = "6.0.1" +mypy = "1.15.0" typing-extensions = ">=3.7.4,<5.0.0" -wemake-python-styleguide = "0.16.0" -bandit = "1.7.2" # https://github.com/PyCQA/bandit/issues/837 +wemake-python-styleguide = "0.19.2" +bandit = "1.8.3" # https://github.com/PyCQA/bandit/issues/837 -pytest = "7.2.0" -pytest-asyncio = "0.16.0" -pytest-cov = "4.0.0" -requests = "2.31.0" -respx = "0.20.2" +pytest = "8.3.5" +pytest-asyncio = "0.26.0" +pytest-cov = "6.1.1" +requests = "2.32.3" +respx = "0.22.0" -fastapi = "0.95.2" -starlette = "0.27.0" # TODO: Drop dependency after updating end-to-end test -uvicorn = "0.16.0" +fastapi = "0.115.12 " +starlette = "0.46.2" # TODO: Drop dependency after updating end-to-end test +uvicorn = "0.34.2" [build-system] -requires = ["poetry>=0.12"] +requires = ["poetry>=2.1.3"] build-backend = "poetry.masonry.api" + +[tool.pytest.ini_options] +asyncio_mode = "auto" +asyncio_default_fixture_loop_scope = "function" diff --git a/tests/client/test_botx_method.py b/tests/client/test_botx_method.py index be2a63e2..b81f97a4 100644 --- a/tests/client/test_botx_method.py +++ b/tests/client/test_botx_method.py @@ -168,7 +168,7 @@ async def test__botx_method__invalid_schema_raises_invalid_botx_response_payload await method.execute(payload) # - Assert - - assert '{"invalid": "schema"}' in str(exc.value) + assert '{"invalid":"schema"}' in str(exc.value) assert endpoint.called diff --git a/tests/test_base_command.py b/tests/test_base_command.py index a361a76d..7e2937e1 100644 --- a/tests/test_base_command.py +++ b/tests/test_base_command.py @@ -21,7 +21,9 @@ ] -async def test__async_execute_raw_bot_command__invalid_payload_value_error_raised() -> None: +async def test__async_execute_raw_bot_command__invalid_payload_value_error_raised() -> ( + None +): # - Arrange - payload = {"invalid": "command"} built_bot = Bot(collectors=[HandlerCollector()], bot_accounts=[]) @@ -35,7 +37,9 @@ async def test__async_execute_raw_bot_command__invalid_payload_value_error_raise assert "validation" in str(exc.value) -async def test__async_execute_raw_bot_command__unsupported_bot_api_version_error_raised() -> None: +async def test__async_execute_raw_bot_command__unsupported_bot_api_version_error_raised() -> ( + None +): # - Arrange - payload = {"proto_version": "3"} built_bot = Bot(collectors=[HandlerCollector()], bot_accounts=[]) diff --git a/tests/test_handler_collector.py b/tests/test_handler_collector.py index 5d86cf73..700df1d1 100644 --- a/tests/test_handler_collector.py +++ b/tests/test_handler_collector.py @@ -146,7 +146,9 @@ async def handler_2(message: IncomingMessage, bot: Bot) -> None: assert "/command" in str(exc.value) -def test__handler_collector__merge_collectors_with_default_handlers_error_raised() -> None: +def test__handler_collector__merge_collectors_with_default_handlers_error_raised() -> ( + None +): # - Arrange - collector = HandlerCollector() @@ -169,7 +171,9 @@ async def handler_2(message: IncomingMessage, bot: Bot) -> None: assert "Default" in str(exc.value) -def test__handler_collector__merge_collectors_with_same_system_events_handlers_error_raised() -> None: +def test__handler_collector__merge_collectors_with_same_system_events_handlers_error_raised() -> ( + None +): # - Arrange - collector = HandlerCollector() @@ -556,7 +560,6 @@ async def test__handler_collector__sync_smartapp_event__decorator__handler_alrea with pytest.raises(ValueError) as exc: @collector.sync_smartapp_event - async def duplicated_handle_sync_smartapp_event(*_: Any) -> Any: - ... + async def duplicated_handle_sync_smartapp_event(*_: Any) -> Any: ... assert str(exc.value) == "Handler for sync smartapp event already registered" From cea867a200748defd073384f6b03102e63a7a776 Mon Sep 17 00:00:00 2001 From: Aleksandr Osovskii Date: Wed, 14 May 2025 16:09:05 +0300 Subject: [PATCH 06/18] mypy fix --- pybotx/async_buffer.py | 3 ++ pybotx/bot/handler.py | 13 ++++++-- pybotx/models/async_files.py | 18 ----------- pybotx/models/attachments.py | 14 ++++----- pybotx/models/message/incoming_message.py | 3 -- tests/client/test_botx_method_callback.py | 2 +- tests/system_events/factories.py | 31 +++++++------------ .../system_events/test_conference_changed.py | 13 +++++--- tests/system_events/test_join_to_chat.py | 9 ++++-- 9 files changed, 47 insertions(+), 59 deletions(-) diff --git a/pybotx/async_buffer.py b/pybotx/async_buffer.py index 141d8080..5ae28f23 100644 --- a/pybotx/async_buffer.py +++ b/pybotx/async_buffer.py @@ -1,3 +1,4 @@ +import abc import os from typing import Optional @@ -18,10 +19,12 @@ async def tell(self) -> int: ... # noqa: WPS428 class AsyncBufferWritable(AsyncBufferBase): + @abc.abstractmethod async def write(self, content: bytes) -> int: ... # noqa: WPS428 class AsyncBufferReadable(AsyncBufferBase): + @abc.abstractmethod async def read( self, bytes_to_read: Optional[int] = None, diff --git a/pybotx/bot/handler.py b/pybotx/bot/handler.py index 4addf2f1..94a4998f 100644 --- a/pybotx/bot/handler.py +++ b/pybotx/bot/handler.py @@ -1,6 +1,15 @@ from dataclasses import dataclass from functools import partial -from typing import TYPE_CHECKING, Awaitable, Callable, List, Literal, TypeVar, Union +from typing import ( + TYPE_CHECKING, + Awaitable, + Callable, + List, + Literal, + TypeVar, + Union, + cast, +) from pybotx.models.commands import BotCommand from pybotx.models.message.incoming_message import IncomingMessage @@ -69,7 +78,7 @@ async def __call__(self, message: IncomingMessage, bot: "Bot") -> None: handler_func = self.handler_func for middleware in self.middlewares[::-1]: - handler_func = partial(middleware, call_next=handler_func) + handler_func = cast(HandlerFunc, partial(middleware, call_next=handler_func)) # type: ignore[type-arg, call-arg] await handler_func(message, bot) diff --git a/pybotx/models/async_files.py b/pybotx/models/async_files.py index 0ecb5f91..f41940e0 100644 --- a/pybotx/models/async_files.py +++ b/pybotx/models/async_files.py @@ -52,7 +52,6 @@ class Image(AsyncFileBase): @dataclass class Video(AsyncFileBase): type: Literal[AttachmentTypes.VIDEO] - duration: int @@ -64,7 +63,6 @@ class Document(AsyncFileBase): @dataclass class Voice(AsyncFileBase): type: Literal[AttachmentTypes.VOICE] - duration: int @@ -78,12 +76,6 @@ class APIAsyncFileBase(VerifiedPayloadBaseModel): file_hash: str class Config: - """BotX sends extra fields which are used by client only. - - We skip their validation, but extra fields will be saved during - serialization/deserialization. - """ - extra = "allow" @@ -93,7 +85,6 @@ class ApiAsyncFileImage(APIAsyncFileBase): class ApiAsyncFileVideo(APIAsyncFileBase): type: Literal[APIAttachmentTypes.VIDEO] - duration: int @@ -103,7 +94,6 @@ class ApiAsyncFileDocument(APIAsyncFileBase): class ApiAsyncFileVoice(APIAsyncFileBase): type: Literal[APIAttachmentTypes.VOICE] - duration: int @@ -121,7 +111,6 @@ def convert_async_file_from_domain(file: File) -> APIAsyncFile: attachment_type = convert_attachment_type_from_domain(file.type) if attachment_type == APIAttachmentTypes.IMAGE: - attachment_type = cast(Literal[APIAttachmentTypes.IMAGE], attachment_type) file = cast(Image, file) return ApiAsyncFileImage( @@ -135,7 +124,6 @@ def convert_async_file_from_domain(file: File) -> APIAsyncFile: ) if attachment_type == APIAttachmentTypes.VIDEO: - attachment_type = cast(Literal[APIAttachmentTypes.VIDEO], attachment_type) file = cast(Video, file) return ApiAsyncFileVideo( @@ -150,7 +138,6 @@ def convert_async_file_from_domain(file: File) -> APIAsyncFile: ) if attachment_type == APIAttachmentTypes.DOCUMENT: - attachment_type = cast(Literal[APIAttachmentTypes.DOCUMENT], attachment_type) file = cast(Document, file) return ApiAsyncFileDocument( @@ -164,7 +151,6 @@ def convert_async_file_from_domain(file: File) -> APIAsyncFile: ) if attachment_type == APIAttachmentTypes.VOICE: - attachment_type = cast(Literal[APIAttachmentTypes.VOICE], attachment_type) file = cast(Voice, file) return ApiAsyncFileVoice( @@ -185,7 +171,6 @@ def convert_async_file_to_domain(async_file: APIAsyncFile) -> File: attachment_type = convert_attachment_type_to_domain(async_file.type) if attachment_type == AttachmentTypes.IMAGE: - attachment_type = cast(Literal[AttachmentTypes.IMAGE], attachment_type) async_file = cast(ApiAsyncFileImage, async_file) return Image( @@ -200,7 +185,6 @@ def convert_async_file_to_domain(async_file: APIAsyncFile) -> File: ) if attachment_type == AttachmentTypes.VIDEO: - attachment_type = cast(Literal[AttachmentTypes.VIDEO], attachment_type) async_file = cast(ApiAsyncFileVideo, async_file) return Video( @@ -216,7 +200,6 @@ def convert_async_file_to_domain(async_file: APIAsyncFile) -> File: ) if attachment_type == AttachmentTypes.DOCUMENT: - attachment_type = cast(Literal[AttachmentTypes.DOCUMENT], attachment_type) async_file = cast(ApiAsyncFileDocument, async_file) return Document( @@ -231,7 +214,6 @@ def convert_async_file_to_domain(async_file: APIAsyncFile) -> File: ) if attachment_type == AttachmentTypes.VOICE: - attachment_type = cast(Literal[AttachmentTypes.VOICE], attachment_type) async_file = cast(ApiAsyncFileVoice, async_file) return Voice( diff --git a/pybotx/models/attachments.py b/pybotx/models/attachments.py index 899fd9ce..0c841f14 100644 --- a/pybotx/models/attachments.py +++ b/pybotx/models/attachments.py @@ -220,7 +220,7 @@ def convert_api_attachment_to_domain( # noqa: WPS212 attachment_type = convert_attachment_type_to_domain(api_attachment.type) if attachment_type == AttachmentTypes.IMAGE: - attachment_type = cast(Literal[AttachmentTypes.IMAGE], attachment_type) + attachment_type = cast(Literal[AttachmentTypes.IMAGE], attachment_type) # type: ignore[redundant-cast] api_attachment = cast(BotAPIAttachmentImage, api_attachment) content = decode_rfc2397(api_attachment.data.content) @@ -233,7 +233,7 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.VIDEO: - attachment_type = cast(Literal[AttachmentTypes.VIDEO], attachment_type) + attachment_type = cast(Literal[AttachmentTypes.VIDEO], attachment_type) # type: ignore[redundant-cast] api_attachment = cast(BotAPIAttachmentVideo, api_attachment) content = decode_rfc2397(api_attachment.data.content) @@ -247,7 +247,7 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.DOCUMENT: - attachment_type = cast(Literal[AttachmentTypes.DOCUMENT], attachment_type) + attachment_type = cast(Literal[AttachmentTypes.DOCUMENT], attachment_type) # type: ignore[redundant-cast] api_attachment = cast(BotAPIAttachmentDocument, api_attachment) content = decode_rfc2397(api_attachment.data.content) @@ -260,7 +260,7 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.VOICE: - attachment_type = cast(Literal[AttachmentTypes.VOICE], attachment_type) + attachment_type = cast(Literal[AttachmentTypes.VOICE], attachment_type) # type: ignore[redundant-cast] api_attachment = cast(BotAPIAttachmentVoice, api_attachment) content = decode_rfc2397(api_attachment.data.content) attachment_extension = get_attachment_extension_from_encoded_content( @@ -277,7 +277,7 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.LOCATION: - attachment_type = cast(Literal[AttachmentTypes.LOCATION], attachment_type) + attachment_type = cast(Literal[AttachmentTypes.LOCATION], attachment_type) # type: ignore[redundant-cast] api_attachment = cast(BotAPIAttachmentLocation, api_attachment) return Location( @@ -288,7 +288,7 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.CONTACT: - attachment_type = cast(Literal[AttachmentTypes.CONTACT], attachment_type) + attachment_type = cast(Literal[AttachmentTypes.CONTACT], attachment_type) # type: ignore[redundant-cast] api_attachment = cast(BotAPIAttachmentContact, api_attachment) return Contact( @@ -296,7 +296,6 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.LINK: - attachment_type = cast(Literal[AttachmentTypes.LINK], attachment_type) api_attachment = cast(BotAPIAttachmentLink, api_attachment) return Link( @@ -307,7 +306,6 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.STICKER: - attachment_type = cast(Literal[AttachmentTypes.STICKER], attachment_type) api_attachment = cast(BotAPIAttachmentSticker, api_attachment) return Sticker( diff --git a/pybotx/models/message/incoming_message.py b/pybotx/models/message/incoming_message.py index 5d494e17..d11a1488 100644 --- a/pybotx/models/message/incoming_message.py +++ b/pybotx/models/message/incoming_message.py @@ -154,11 +154,9 @@ def _convert_bot_api_mention_to_domain(api_mention_data: BotAPIMentionData) -> M def convert_bot_api_entity_to_domain(api_entity: BotAPIEntity) -> Entity: if api_entity.type == BotAPIEntityTypes.MENTION: - api_entity = cast(BotAPIMention, api_entity) return _convert_bot_api_mention_to_domain(api_entity.data) if api_entity.type == BotAPIEntityTypes.FORWARD: - api_entity = cast(BotAPIForward, api_entity) return Forward( chat_id=api_entity.data.group_chat_id, @@ -170,7 +168,6 @@ def convert_bot_api_entity_to_domain(api_entity: BotAPIEntity) -> Entity: ) if api_entity.type == BotAPIEntityTypes.REPLY: - api_entity = cast(BotAPIReply, api_entity) mentions = MentionList() for api_mention_data in api_entity.data.mentions: diff --git a/tests/client/test_botx_method_callback.py b/tests/client/test_botx_method_callback.py index 95781111..3b609646 100644 --- a/tests/client/test_botx_method_callback.py +++ b/tests/client/test_botx_method_callback.py @@ -1,4 +1,4 @@ -# type: ignore [attr-defined] +# mypy: disable-error-code=attr-defined import asyncio import time diff --git a/tests/system_events/factories.py b/tests/system_events/factories.py index bb84df76..264874da 100644 --- a/tests/system_events/factories.py +++ b/tests/system_events/factories.py @@ -1,18 +1,17 @@ import uuid from typing import Any, Dict, List, Optional -from factory.base import DictFactory # type: ignore -from factory.declarations import SubFactory # type: ignore +from factory.base import DictFactory +from factory.declarations import SubFactory -class DeviceMetaFactory(DictFactory): # type: ignore[misc] - +class DeviceMetaFactory(DictFactory): permissions: Optional[str] = None pushes: Optional[str] = None timezone: Optional[str] = None -class FromFactory(DictFactory): # type: ignore[misc] +class FromFactory(DictFactory): user_huid: Optional[str] = None group_chat_id: str = "8dada2c8-67a6-4434-9dec-570d244e78ee" ad_login: Optional[str] = None @@ -22,7 +21,7 @@ class FromFactory(DictFactory): # type: ignore[misc] manufacturer: Optional[str] = None device: Optional[str] = None device_software: Optional[str] = None - device_meta: Dict[str, Any] = SubFactory(DeviceMetaFactory) # noqa: F821 + device_meta: Any = SubFactory(DeviceMetaFactory) # type: ignore[no-untyped-call] platform: Optional[str] = None platform_package_id: Optional[str] = None is_admin: Optional[bool] = None @@ -32,29 +31,24 @@ class FromFactory(DictFactory): # type: ignore[misc] host: str = "cts.ccteam.ru" -class CommandDataFactory(DictFactory): # type: ignore[misc] - +class CommandDataFactory(DictFactory): added_members: List[str] = [uuid.uuid4().hex, uuid.uuid4().hex] -class CommandFactory(DictFactory): # type: ignore[misc] - +class CommandFactory(DictFactory): body: str = "system:user_joined_to_chat" command_type: str = "system" - data: Dict[str, Any] = SubFactory(CommandDataFactory) # noqa: F821 + data: Any = SubFactory(CommandDataFactory) # type: ignore[no-untyped-call] metadata: Dict[str, Any] = {} -class BotAPIJoinToChatFactory(DictFactory): # type: ignore[misc] - +class BotAPIJoinToChatFactory(DictFactory): sync_id: str = uuid.uuid4().hex - command: Dict[str, Any] = SubFactory(CommandFactory) # noqa: F821 + command: Any = SubFactory(CommandFactory) # type: ignore[no-untyped-call] async_files: List[str] = [] attachments: List[str] = [] entities: List[str] = [] - from_: Dict[str, Any] = SubFactory( - FromFactory, - ) # noqa: F821 + from_: Any = SubFactory(FromFactory) # type: ignore[no-untyped-call] bot_id: str = uuid.uuid4().hex proto_version: int = 4 source_sync_id: Optional[str] = None @@ -63,8 +57,7 @@ class Meta: rename = {"from_": "from"} -class ConferenceChangedDataFactory(DictFactory): # type: ignore[misc] - +class ConferenceChangedDataFactory(DictFactory): access_code = None actor = None added_users = ["5c053f2a-0bdf-4ab1-9bc9-256fee9db7ba"] diff --git a/tests/system_events/test_conference_changed.py b/tests/system_events/test_conference_changed.py index 3dc6ad5c..66eea67e 100644 --- a/tests/system_events/test_conference_changed.py +++ b/tests/system_events/test_conference_changed.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import Any, Callable, Dict, Optional +from typing import Any, Callable, Dict, Optional, cast from uuid import UUID import pytest @@ -14,7 +14,7 @@ ) from pybotx.models.enums import ConferenceLinkTypes from pybotx.models.system_events.conference_changed import ConferenceChangedEvent -from tests.system_events.factories import ConferenceChangedDataFactory # type: ignore +from tests.system_events.factories import ConferenceChangedDataFactory pytestmark = [ pytest.mark.asyncio, @@ -32,9 +32,12 @@ async def test__conference_changed_succeed( api_incoming_message_factory: Callable[..., Dict[str, Any]], ) -> None: # - Arrange - - conference_change_data = ConferenceChangedDataFactory( - call_id=str(call_id), - link_type="public", + conference_change_data = cast( + Dict[str, Any], + ConferenceChangedDataFactory( + call_id=str(call_id), + link_type="public", + ), # type: ignore[no-untyped-call] ) payload = api_incoming_message_factory( body="system:conference_changed", diff --git a/tests/system_events/test_join_to_chat.py b/tests/system_events/test_join_to_chat.py index 6b66fbd4..16622787 100644 --- a/tests/system_events/test_join_to_chat.py +++ b/tests/system_events/test_join_to_chat.py @@ -1,4 +1,4 @@ -from typing import Any, Optional +from typing import Any, Dict, Optional, cast from uuid import UUID import pytest @@ -13,7 +13,7 @@ lifespan_wrapper, ) from pybotx.models.system_events.user_joined_to_chat import JoinToChatEvent -from tests.system_events.factories import BotAPIJoinToChatFactory # type: ignore +from tests.system_events.factories import BotAPIJoinToChatFactory pytestmark = [ pytest.mark.asyncio, @@ -33,7 +33,10 @@ async def test__join_to_chat__succeed( 3. The registered user_joined_to_chat handler is called with this event """ - payload: dict[str, Any] = BotAPIJoinToChatFactory(bot_id=bot_account.id.hex) + payload: Dict[str, Any] = cast( + Dict[str, Any], + BotAPIJoinToChatFactory(bot_id=bot_account.id.hex), # type: ignore[no-untyped-call] + ) collector = HandlerCollector() join_to_chat: Optional[JoinToChatEvent] = None From 221d81b7677accb944a0f82a83f865ea430152fc Mon Sep 17 00:00:00 2001 From: Aleksandr Osovskii Date: Wed, 14 May 2025 16:23:41 +0300 Subject: [PATCH 07/18] flake8 fix --- pybotx/async_buffer.py | 8 +++--- pybotx/bot/callbacks/callback_manager.py | 4 +-- pybotx/bot/callbacks/callback_repo_proto.py | 10 +++---- pybotx/bot/handler.py | 5 +++- pybotx/bot/handler_collector.py | 4 +-- pybotx/models/attachments.py | 30 ++++++++++++++++----- pybotx/models/chats.py | 3 +-- pybotx/models/enums.py | 8 +++--- tests/test_handler_collector.py | 2 +- tests/test_middlewares.py | 6 ++--- 10 files changed, 50 insertions(+), 30 deletions(-) diff --git a/pybotx/async_buffer.py b/pybotx/async_buffer.py index 5ae28f23..4b59b7e8 100644 --- a/pybotx/async_buffer.py +++ b/pybotx/async_buffer.py @@ -13,14 +13,14 @@ async def seek( self, cursor: int, whence: int = os.SEEK_SET, - ) -> int: ... # noqa: WPS428 + ) -> int: ... # noqa: WPS428, E704 - async def tell(self) -> int: ... # noqa: WPS428 + async def tell(self) -> int: ... # noqa: WPS428, E704 class AsyncBufferWritable(AsyncBufferBase): @abc.abstractmethod - async def write(self, content: bytes) -> int: ... # noqa: WPS428 + async def write(self, content: bytes) -> int: ... # noqa: WPS428, E704 class AsyncBufferReadable(AsyncBufferBase): @@ -28,7 +28,7 @@ class AsyncBufferReadable(AsyncBufferBase): async def read( self, bytes_to_read: Optional[int] = None, - ) -> bytes: ... # noqa: WPS428 + ) -> bytes: ... # noqa: WPS428, E704 async def get_file_size(async_buffer: AsyncBufferReadable) -> int: diff --git a/pybotx/bot/callbacks/callback_manager.py b/pybotx/bot/callbacks/callback_manager.py index e9145fe3..7b17a2b9 100644 --- a/pybotx/bot/callbacks/callback_manager.py +++ b/pybotx/bot/callbacks/callback_manager.py @@ -69,14 +69,14 @@ def setup_callback_timeout_alarm(self, sync_id: UUID, timeout: float) -> None: def cancel_callback_timeout_alarm( self, sync_id: UUID, - ) -> None: ... # noqa: WPS428 + ) -> None: ... # noqa: WPS428, E704 @overload def cancel_callback_timeout_alarm( self, sync_id: UUID, return_remaining_time: Literal[True], - ) -> float: ... # noqa: WPS428 + ) -> float: ... # noqa: WPS428, E704 def cancel_callback_timeout_alarm( self, diff --git a/pybotx/bot/callbacks/callback_repo_proto.py b/pybotx/bot/callbacks/callback_repo_proto.py index 26a3d2a4..7c34bf11 100644 --- a/pybotx/bot/callbacks/callback_repo_proto.py +++ b/pybotx/bot/callbacks/callback_repo_proto.py @@ -16,22 +16,22 @@ class CallbackRepoProto(Protocol): async def create_botx_method_callback( self, sync_id: UUID, - ) -> None: ... # noqa: WPS428 + ) -> None: ... # noqa: WPS428, E704 async def set_botx_method_callback_result( self, callback: BotXMethodCallback, - ) -> None: ... # noqa: WPS428 + ) -> None: ... # noqa: WPS428, E704 async def wait_botx_method_callback( self, sync_id: UUID, timeout: float, - ) -> BotXMethodCallback: ... # noqa: WPS428 + ) -> BotXMethodCallback: ... # noqa: WPS428, E704 async def pop_botx_method_callback( self, sync_id: UUID, - ) -> "Future[BotXMethodCallback]": ... # noqa: WPS428 + ) -> "Future[BotXMethodCallback]": ... # noqa: WPS428, E704 - async def stop_callbacks_waiting(self) -> None: ... # noqa: WPS428 + async def stop_callbacks_waiting(self) -> None: ... # noqa: WPS428, E704 diff --git a/pybotx/bot/handler.py b/pybotx/bot/handler.py index 94a4998f..899cd997 100644 --- a/pybotx/bot/handler.py +++ b/pybotx/bot/handler.py @@ -78,7 +78,10 @@ async def __call__(self, message: IncomingMessage, bot: "Bot") -> None: handler_func = self.handler_func for middleware in self.middlewares[::-1]: - handler_func = cast(HandlerFunc, partial(middleware, call_next=handler_func)) # type: ignore[type-arg, call-arg] + handler_func = cast( + HandlerFunc, + partial(middleware, call_next=handler_func), + ) # type: ignore[type-arg, call-arg] await handler_func(message, bot) diff --git a/pybotx/bot/handler_collector.py b/pybotx/bot/handler_collector.py index 35599f5a..7cc276af 100644 --- a/pybotx/bot/handler_collector.py +++ b/pybotx/bot/handler_collector.py @@ -194,7 +194,7 @@ def decorator( def default_message_handler( self, handler_func: IncomingMessageHandlerFunc, - ) -> IncomingMessageHandlerFunc: ... # noqa: WPS428 + ) -> IncomingMessageHandlerFunc: ... # noqa: WPS428, E704 @overload def default_message_handler( @@ -204,7 +204,7 @@ def default_message_handler( ) -> Callable[ [IncomingMessageHandlerFunc], IncomingMessageHandlerFunc, - ]: ... # noqa: WPS428 + ]: ... # noqa: WPS428, E704 def default_message_handler( # noqa: WPS320 self, diff --git a/pybotx/models/attachments.py b/pybotx/models/attachments.py index 0c841f14..df50fc0c 100644 --- a/pybotx/models/attachments.py +++ b/pybotx/models/attachments.py @@ -220,7 +220,10 @@ def convert_api_attachment_to_domain( # noqa: WPS212 attachment_type = convert_attachment_type_to_domain(api_attachment.type) if attachment_type == AttachmentTypes.IMAGE: - attachment_type = cast(Literal[AttachmentTypes.IMAGE], attachment_type) # type: ignore[redundant-cast] + attachment_type = cast( + Literal[AttachmentTypes.IMAGE], + attachment_type, + ) # type: ignore[redundant-cast] api_attachment = cast(BotAPIAttachmentImage, api_attachment) content = decode_rfc2397(api_attachment.data.content) @@ -233,7 +236,10 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.VIDEO: - attachment_type = cast(Literal[AttachmentTypes.VIDEO], attachment_type) # type: ignore[redundant-cast] + attachment_type = cast( + Literal[AttachmentTypes.VIDEO], + attachment_type, + ) # type: ignore[redundant-cast] api_attachment = cast(BotAPIAttachmentVideo, api_attachment) content = decode_rfc2397(api_attachment.data.content) @@ -247,7 +253,10 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.DOCUMENT: - attachment_type = cast(Literal[AttachmentTypes.DOCUMENT], attachment_type) # type: ignore[redundant-cast] + attachment_type = cast( + Literal[AttachmentTypes.DOCUMENT], + attachment_type, + ) # type: ignore[redundant-cast] api_attachment = cast(BotAPIAttachmentDocument, api_attachment) content = decode_rfc2397(api_attachment.data.content) @@ -260,7 +269,10 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.VOICE: - attachment_type = cast(Literal[AttachmentTypes.VOICE], attachment_type) # type: ignore[redundant-cast] + attachment_type = cast( + Literal[AttachmentTypes.VOICE], + attachment_type, + ) # type: ignore[redundant-cast] api_attachment = cast(BotAPIAttachmentVoice, api_attachment) content = decode_rfc2397(api_attachment.data.content) attachment_extension = get_attachment_extension_from_encoded_content( @@ -277,7 +289,10 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.LOCATION: - attachment_type = cast(Literal[AttachmentTypes.LOCATION], attachment_type) # type: ignore[redundant-cast] + attachment_type = cast( + Literal[AttachmentTypes.LOCATION], + attachment_type, + ) # type: ignore[redundant-cast] api_attachment = cast(BotAPIAttachmentLocation, api_attachment) return Location( @@ -288,7 +303,10 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.CONTACT: - attachment_type = cast(Literal[AttachmentTypes.CONTACT], attachment_type) # type: ignore[redundant-cast] + attachment_type = cast( + Literal[AttachmentTypes.CONTACT], + attachment_type, + ) # type: ignore[redundant-cast] api_attachment = cast(BotAPIAttachmentContact, api_attachment) return Contact( diff --git a/pybotx/models/chats.py b/pybotx/models/chats.py index c82aaf44..817879cc 100644 --- a/pybotx/models/chats.py +++ b/pybotx/models/chats.py @@ -1,6 +1,5 @@ from dataclasses import dataclass from datetime import datetime -from datetime import datetime as dt from typing import List, Optional from uuid import UUID @@ -72,7 +71,7 @@ class ChatInfo: creator_id: Optional[UUID] description: Optional[str] chat_id: UUID - created_at: dt + created_at: datetime members: List[ChatInfoMember] name: str shared_history: bool diff --git a/pybotx/models/enums.py b/pybotx/models/enums.py index 0f4d06f1..79fe6658 100644 --- a/pybotx/models/enums.py +++ b/pybotx/models/enums.py @@ -307,11 +307,11 @@ def convert_chat_type_from_domain(chat_type: ChatTypes) -> APIChatTypes: @overload def convert_chat_type_to_domain( chat_type: APIChatTypes, -) -> ChatTypes: ... # noqa: WPS428 +) -> ChatTypes: ... # noqa: WPS428, E704 @overload -def convert_chat_type_to_domain(chat_type: str) -> UNSUPPORTED: ... # noqa: WPS428 +def convert_chat_type_to_domain(chat_type: str) -> UNSUPPORTED: ... # noqa: WPS428, E704 def convert_chat_type_to_domain( @@ -338,13 +338,13 @@ def convert_chat_type_to_domain( @overload def convert_sync_source_type_to_domain( sync_type: APISyncSourceTypes, -) -> SyncSourceTypes: ... # noqa: WPS428 +) -> SyncSourceTypes: ... # noqa: WPS428, E704 @overload def convert_sync_source_type_to_domain( sync_type: str, -) -> UNSUPPORTED: ... # noqa: WPS428 +) -> UNSUPPORTED: ... # noqa: WPS428, E704 def convert_sync_source_type_to_domain( diff --git a/tests/test_handler_collector.py b/tests/test_handler_collector.py index 700df1d1..2fb9b052 100644 --- a/tests/test_handler_collector.py +++ b/tests/test_handler_collector.py @@ -560,6 +560,6 @@ async def test__handler_collector__sync_smartapp_event__decorator__handler_alrea with pytest.raises(ValueError) as exc: @collector.sync_smartapp_event - async def duplicated_handle_sync_smartapp_event(*_: Any) -> Any: ... + async def duplicated_handle_sync_smartapp_event(*_: Any) -> Any: ... # noqa: E704 assert str(exc.value) == "Handler for sync smartapp event already registered" diff --git a/tests/test_middlewares.py b/tests/test_middlewares.py index 62dddca1..54aef7f9 100644 --- a/tests/test_middlewares.py +++ b/tests/test_middlewares.py @@ -35,7 +35,7 @@ async def middleware( bot: Bot, call_next: IncomingMessageHandlerFunc, ) -> None: - nonlocal middlewares_called_order + # middlewares_called_order is already accessible in this scope middlewares_called_order.append(number) await call_next(message, bot) @@ -84,7 +84,7 @@ async def middleware( bot: Bot, call_next: IncomingMessageHandlerFunc, ) -> None: - nonlocal middlewares_called_order + # middlewares_called_order is already accessible in this scope middlewares_called_order.append(number) await call_next(message, bot) @@ -129,7 +129,7 @@ async def middleware( bot: Bot, call_next: IncomingMessageHandlerFunc, ) -> None: - nonlocal middlewares_called_order + # middlewares_called_order is already accessible in this scope middlewares_called_order.append(number) await call_next(message, bot) From 64d4e6dfe7107d7c15e010b26d7b50294a3b568d Mon Sep 17 00:00:00 2001 From: Aleksandr Osovskii Date: Wed, 14 May 2025 16:26:05 +0300 Subject: [PATCH 08/18] format files --- pybotx/models/enums.py | 4 +++- tests/test_handler_collector.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pybotx/models/enums.py b/pybotx/models/enums.py index 79fe6658..05bc35fa 100644 --- a/pybotx/models/enums.py +++ b/pybotx/models/enums.py @@ -311,7 +311,9 @@ def convert_chat_type_to_domain( @overload -def convert_chat_type_to_domain(chat_type: str) -> UNSUPPORTED: ... # noqa: WPS428, E704 +def convert_chat_type_to_domain( + chat_type: str, +) -> UNSUPPORTED: ... # noqa: WPS428, E704 def convert_chat_type_to_domain( diff --git a/tests/test_handler_collector.py b/tests/test_handler_collector.py index 2fb9b052..727227f0 100644 --- a/tests/test_handler_collector.py +++ b/tests/test_handler_collector.py @@ -560,6 +560,8 @@ async def test__handler_collector__sync_smartapp_event__decorator__handler_alrea with pytest.raises(ValueError) as exc: @collector.sync_smartapp_event - async def duplicated_handle_sync_smartapp_event(*_: Any) -> Any: ... # noqa: E704 + async def duplicated_handle_sync_smartapp_event( + *_: Any, + ) -> Any: ... # noqa: E704 assert str(exc.value) == "Handler for sync smartapp event already registered" From ab9d69222a797632f81f4cfc2f22a9d269a31ee7 Mon Sep 17 00:00:00 2001 From: Aleksandr Osovskii Date: Wed, 14 May 2025 16:32:46 +0300 Subject: [PATCH 09/18] format files --- pybotx/bot/handler.py | 6 +----- pybotx/models/attachments.py | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/pybotx/bot/handler.py b/pybotx/bot/handler.py index 899cd997..6c7164a1 100644 --- a/pybotx/bot/handler.py +++ b/pybotx/bot/handler.py @@ -8,7 +8,6 @@ Literal, TypeVar, Union, - cast, ) from pybotx.models.commands import BotCommand @@ -78,10 +77,7 @@ async def __call__(self, message: IncomingMessage, bot: "Bot") -> None: handler_func = self.handler_func for middleware in self.middlewares[::-1]: - handler_func = cast( - HandlerFunc, - partial(middleware, call_next=handler_func), - ) # type: ignore[type-arg, call-arg] + handler_func = partial(middleware, call_next=handler_func) # type: ignore[call-arg] await handler_func(message, bot) diff --git a/pybotx/models/attachments.py b/pybotx/models/attachments.py index df50fc0c..628434f2 100644 --- a/pybotx/models/attachments.py +++ b/pybotx/models/attachments.py @@ -220,10 +220,10 @@ def convert_api_attachment_to_domain( # noqa: WPS212 attachment_type = convert_attachment_type_to_domain(api_attachment.type) if attachment_type == AttachmentTypes.IMAGE: - attachment_type = cast( + attachment_type = cast( # type: ignore[redundant-cast] Literal[AttachmentTypes.IMAGE], attachment_type, - ) # type: ignore[redundant-cast] + ) api_attachment = cast(BotAPIAttachmentImage, api_attachment) content = decode_rfc2397(api_attachment.data.content) @@ -236,10 +236,10 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.VIDEO: - attachment_type = cast( + attachment_type = cast( # type: ignore[redundant-cast] Literal[AttachmentTypes.VIDEO], attachment_type, - ) # type: ignore[redundant-cast] + ) api_attachment = cast(BotAPIAttachmentVideo, api_attachment) content = decode_rfc2397(api_attachment.data.content) @@ -253,10 +253,10 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.DOCUMENT: - attachment_type = cast( + attachment_type = cast( # type: ignore[redundant-cast] Literal[AttachmentTypes.DOCUMENT], attachment_type, - ) # type: ignore[redundant-cast] + ) api_attachment = cast(BotAPIAttachmentDocument, api_attachment) content = decode_rfc2397(api_attachment.data.content) @@ -269,10 +269,10 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.VOICE: - attachment_type = cast( + attachment_type = cast( # type: ignore[redundant-cast] Literal[AttachmentTypes.VOICE], attachment_type, - ) # type: ignore[redundant-cast] + ) api_attachment = cast(BotAPIAttachmentVoice, api_attachment) content = decode_rfc2397(api_attachment.data.content) attachment_extension = get_attachment_extension_from_encoded_content( @@ -289,10 +289,10 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.LOCATION: - attachment_type = cast( + attachment_type = cast( # type: ignore[redundant-cast] Literal[AttachmentTypes.LOCATION], attachment_type, - ) # type: ignore[redundant-cast] + ) api_attachment = cast(BotAPIAttachmentLocation, api_attachment) return Location( @@ -303,10 +303,10 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.CONTACT: - attachment_type = cast( + attachment_type = cast( # type: ignore[redundant-cast] Literal[AttachmentTypes.CONTACT], attachment_type, - ) # type: ignore[redundant-cast] + ) api_attachment = cast(BotAPIAttachmentContact, api_attachment) return Contact( From 071b6c1108ac8eef9ae865ab81ba602b86e41880 Mon Sep 17 00:00:00 2001 From: Aleksandr Osovskii Date: Wed, 14 May 2025 16:48:48 +0300 Subject: [PATCH 10/18] format files --- pybotx/async_buffer.py | 13 ++++++++----- pybotx/bot/callbacks/callback_manager.py | 6 ++++-- pybotx/bot/callbacks/callback_repo_proto.py | 12 ++++++++---- pybotx/bot/handler.py | 5 ++++- pybotx/bot/handler_collector.py | 9 ++++----- pybotx/models/enums.py | 12 ++++++++---- tests/test_handler_collector.py | 3 ++- tests/test_middlewares.py | 11 ++++------- 8 files changed, 42 insertions(+), 29 deletions(-) diff --git a/pybotx/async_buffer.py b/pybotx/async_buffer.py index 4b59b7e8..6c448e9a 100644 --- a/pybotx/async_buffer.py +++ b/pybotx/async_buffer.py @@ -13,14 +13,17 @@ async def seek( self, cursor: int, whence: int = os.SEEK_SET, - ) -> int: ... # noqa: WPS428, E704 + ) -> int: + ... - async def tell(self) -> int: ... # noqa: WPS428, E704 + async def tell(self) -> int: + ... class AsyncBufferWritable(AsyncBufferBase): @abc.abstractmethod - async def write(self, content: bytes) -> int: ... # noqa: WPS428, E704 + async def write(self, content: bytes) -> int: + ... class AsyncBufferReadable(AsyncBufferBase): @@ -28,12 +31,12 @@ class AsyncBufferReadable(AsyncBufferBase): async def read( self, bytes_to_read: Optional[int] = None, - ) -> bytes: ... # noqa: WPS428, E704 + ) -> bytes: + ... async def get_file_size(async_buffer: AsyncBufferReadable) -> int: await async_buffer.seek(0, os.SEEK_END) file_size = await async_buffer.tell() await async_buffer.seek(0) - return file_size diff --git a/pybotx/bot/callbacks/callback_manager.py b/pybotx/bot/callbacks/callback_manager.py index 7b17a2b9..d4852202 100644 --- a/pybotx/bot/callbacks/callback_manager.py +++ b/pybotx/bot/callbacks/callback_manager.py @@ -69,14 +69,16 @@ def setup_callback_timeout_alarm(self, sync_id: UUID, timeout: float) -> None: def cancel_callback_timeout_alarm( self, sync_id: UUID, - ) -> None: ... # noqa: WPS428, E704 + ) -> None: + ... # noqa: WPS428, E704 @overload def cancel_callback_timeout_alarm( self, sync_id: UUID, return_remaining_time: Literal[True], - ) -> float: ... # noqa: WPS428, E704 + ) -> float: + ... # noqa: WPS428, E704 def cancel_callback_timeout_alarm( self, diff --git a/pybotx/bot/callbacks/callback_repo_proto.py b/pybotx/bot/callbacks/callback_repo_proto.py index 7c34bf11..871575fd 100644 --- a/pybotx/bot/callbacks/callback_repo_proto.py +++ b/pybotx/bot/callbacks/callback_repo_proto.py @@ -16,22 +16,26 @@ class CallbackRepoProto(Protocol): async def create_botx_method_callback( self, sync_id: UUID, - ) -> None: ... # noqa: WPS428, E704 + ) -> None: + ... # noqa: WPS428, E704 async def set_botx_method_callback_result( self, callback: BotXMethodCallback, - ) -> None: ... # noqa: WPS428, E704 + ) -> None: + ... # noqa: WPS428, E704 async def wait_botx_method_callback( self, sync_id: UUID, timeout: float, - ) -> BotXMethodCallback: ... # noqa: WPS428, E704 + ) -> BotXMethodCallback: + ... # noqa: WPS428, E704 async def pop_botx_method_callback( self, sync_id: UUID, - ) -> "Future[BotXMethodCallback]": ... # noqa: WPS428, E704 + ) -> "Future[BotXMethodCallback]": + ... # noqa: WPS428, E704 async def stop_callbacks_waiting(self) -> None: ... # noqa: WPS428, E704 diff --git a/pybotx/bot/handler.py b/pybotx/bot/handler.py index 6c7164a1..a4933e31 100644 --- a/pybotx/bot/handler.py +++ b/pybotx/bot/handler.py @@ -77,7 +77,10 @@ async def __call__(self, message: IncomingMessage, bot: "Bot") -> None: handler_func = self.handler_func for middleware in self.middlewares[::-1]: - handler_func = partial(middleware, call_next=handler_func) # type: ignore[call-arg] + handler_func = partial( + middleware, + call_next=handler_func, # type: ignore[call-arg] + ) await handler_func(message, bot) diff --git a/pybotx/bot/handler_collector.py b/pybotx/bot/handler_collector.py index 7cc276af..a5be0f1d 100644 --- a/pybotx/bot/handler_collector.py +++ b/pybotx/bot/handler_collector.py @@ -194,17 +194,16 @@ def decorator( def default_message_handler( self, handler_func: IncomingMessageHandlerFunc, - ) -> IncomingMessageHandlerFunc: ... # noqa: WPS428, E704 + ) -> IncomingMessageHandlerFunc: + ... # noqa: WPS428, E704 @overload def default_message_handler( self, *, middlewares: Optional[Sequence[Middleware]] = None, - ) -> Callable[ - [IncomingMessageHandlerFunc], - IncomingMessageHandlerFunc, - ]: ... # noqa: WPS428, E704 + ) -> Callable[[IncomingMessageHandlerFunc], IncomingMessageHandlerFunc]: + ... # noqa: WPS428, E704 def default_message_handler( # noqa: WPS320 self, diff --git a/pybotx/models/enums.py b/pybotx/models/enums.py index 05bc35fa..b8a4c446 100644 --- a/pybotx/models/enums.py +++ b/pybotx/models/enums.py @@ -307,13 +307,15 @@ def convert_chat_type_from_domain(chat_type: ChatTypes) -> APIChatTypes: @overload def convert_chat_type_to_domain( chat_type: APIChatTypes, -) -> ChatTypes: ... # noqa: WPS428, E704 +) -> ChatTypes: + ... # noqa: WPS428, E704 @overload def convert_chat_type_to_domain( chat_type: str, -) -> UNSUPPORTED: ... # noqa: WPS428, E704 +) -> UNSUPPORTED: + ... # noqa: WPS428, E704 def convert_chat_type_to_domain( @@ -340,13 +342,15 @@ def convert_chat_type_to_domain( @overload def convert_sync_source_type_to_domain( sync_type: APISyncSourceTypes, -) -> SyncSourceTypes: ... # noqa: WPS428, E704 +) -> SyncSourceTypes: + ... # noqa: WPS428, E704 @overload def convert_sync_source_type_to_domain( sync_type: str, -) -> UNSUPPORTED: ... # noqa: WPS428, E704 +) -> UNSUPPORTED: + ... # noqa: WPS428, E704 def convert_sync_source_type_to_domain( diff --git a/tests/test_handler_collector.py b/tests/test_handler_collector.py index 727227f0..40304ece 100644 --- a/tests/test_handler_collector.py +++ b/tests/test_handler_collector.py @@ -562,6 +562,7 @@ async def test__handler_collector__sync_smartapp_event__decorator__handler_alrea @collector.sync_smartapp_event async def duplicated_handle_sync_smartapp_event( *_: Any, - ) -> Any: ... # noqa: E704 + ) -> Any: + ... # noqa: E704 assert str(exc.value) == "Handler for sync smartapp event already registered" diff --git a/tests/test_middlewares.py b/tests/test_middlewares.py index 54aef7f9..f573051b 100644 --- a/tests/test_middlewares.py +++ b/tests/test_middlewares.py @@ -35,8 +35,7 @@ async def middleware( bot: Bot, call_next: IncomingMessageHandlerFunc, ) -> None: - # middlewares_called_order is already accessible in this scope - middlewares_called_order.append(number) + middlewares_called_order.append(number) # noqa: F824 await call_next(message, bot) @@ -84,8 +83,7 @@ async def middleware( bot: Bot, call_next: IncomingMessageHandlerFunc, ) -> None: - # middlewares_called_order is already accessible in this scope - middlewares_called_order.append(number) + middlewares_called_order.append(number) # noqa: F824 await call_next(message, bot) @@ -129,8 +127,7 @@ async def middleware( bot: Bot, call_next: IncomingMessageHandlerFunc, ) -> None: - # middlewares_called_order is already accessible in this scope - middlewares_called_order.append(number) + middlewares_called_order.append(number) # noqa: F824 await call_next(message, bot) @@ -177,7 +174,7 @@ async def middleware( bot: Bot, call_next: IncomingMessageHandlerFunc, ) -> None: - nonlocal middlewares_called_order + nonlocal middlewares_called_order # noqa: F824 middlewares_called_order.append(number) await call_next(message, bot) From d58468218da0639fb77598b2bc8303213ca614f7 Mon Sep 17 00:00:00 2001 From: Aleksandr Osovskii Date: Wed, 14 May 2025 16:59:13 +0300 Subject: [PATCH 11/18] format files --- pybotx/async_buffer.py | 12 ++++-------- pybotx/bot/callbacks/callback_manager.py | 6 ++---- pybotx/bot/callbacks/callback_repo_proto.py | 12 ++++-------- pybotx/bot/handler_collector.py | 11 +++++++---- pybotx/models/enums.py | 12 ++++-------- setup.cfg | 1 + tests/test_handler_collector.py | 3 +-- 7 files changed, 23 insertions(+), 34 deletions(-) diff --git a/pybotx/async_buffer.py b/pybotx/async_buffer.py index 6c448e9a..ab965560 100644 --- a/pybotx/async_buffer.py +++ b/pybotx/async_buffer.py @@ -13,17 +13,14 @@ async def seek( self, cursor: int, whence: int = os.SEEK_SET, - ) -> int: - ... + ) -> int: ... - async def tell(self) -> int: - ... + async def tell(self) -> int: ... class AsyncBufferWritable(AsyncBufferBase): @abc.abstractmethod - async def write(self, content: bytes) -> int: - ... + async def write(self, content: bytes) -> int: ... class AsyncBufferReadable(AsyncBufferBase): @@ -31,8 +28,7 @@ class AsyncBufferReadable(AsyncBufferBase): async def read( self, bytes_to_read: Optional[int] = None, - ) -> bytes: - ... + ) -> bytes: ... async def get_file_size(async_buffer: AsyncBufferReadable) -> int: diff --git a/pybotx/bot/callbacks/callback_manager.py b/pybotx/bot/callbacks/callback_manager.py index d4852202..7b17a2b9 100644 --- a/pybotx/bot/callbacks/callback_manager.py +++ b/pybotx/bot/callbacks/callback_manager.py @@ -69,16 +69,14 @@ def setup_callback_timeout_alarm(self, sync_id: UUID, timeout: float) -> None: def cancel_callback_timeout_alarm( self, sync_id: UUID, - ) -> None: - ... # noqa: WPS428, E704 + ) -> None: ... # noqa: WPS428, E704 @overload def cancel_callback_timeout_alarm( self, sync_id: UUID, return_remaining_time: Literal[True], - ) -> float: - ... # noqa: WPS428, E704 + ) -> float: ... # noqa: WPS428, E704 def cancel_callback_timeout_alarm( self, diff --git a/pybotx/bot/callbacks/callback_repo_proto.py b/pybotx/bot/callbacks/callback_repo_proto.py index 871575fd..7c34bf11 100644 --- a/pybotx/bot/callbacks/callback_repo_proto.py +++ b/pybotx/bot/callbacks/callback_repo_proto.py @@ -16,26 +16,22 @@ class CallbackRepoProto(Protocol): async def create_botx_method_callback( self, sync_id: UUID, - ) -> None: - ... # noqa: WPS428, E704 + ) -> None: ... # noqa: WPS428, E704 async def set_botx_method_callback_result( self, callback: BotXMethodCallback, - ) -> None: - ... # noqa: WPS428, E704 + ) -> None: ... # noqa: WPS428, E704 async def wait_botx_method_callback( self, sync_id: UUID, timeout: float, - ) -> BotXMethodCallback: - ... # noqa: WPS428, E704 + ) -> BotXMethodCallback: ... # noqa: WPS428, E704 async def pop_botx_method_callback( self, sync_id: UUID, - ) -> "Future[BotXMethodCallback]": - ... # noqa: WPS428, E704 + ) -> "Future[BotXMethodCallback]": ... # noqa: WPS428, E704 async def stop_callbacks_waiting(self) -> None: ... # noqa: WPS428, E704 diff --git a/pybotx/bot/handler_collector.py b/pybotx/bot/handler_collector.py index a5be0f1d..3d07d146 100644 --- a/pybotx/bot/handler_collector.py +++ b/pybotx/bot/handler_collector.py @@ -59,6 +59,11 @@ if TYPE_CHECKING: # To avoid circular import from pybotx.bot.bot import Bot +MessageHandlerDecorator = Callable[ + [IncomingMessageHandlerFunc], + IncomingMessageHandlerFunc, +] + class HandlerCollector: VALID_COMMAND_NAME_RE = re.compile(r"^\/[^\s\/]+$", flags=re.UNICODE) @@ -194,16 +199,14 @@ def decorator( def default_message_handler( self, handler_func: IncomingMessageHandlerFunc, - ) -> IncomingMessageHandlerFunc: - ... # noqa: WPS428, E704 + ) -> IncomingMessageHandlerFunc: ... # noqa: WPS428, E704 @overload def default_message_handler( self, *, middlewares: Optional[Sequence[Middleware]] = None, - ) -> Callable[[IncomingMessageHandlerFunc], IncomingMessageHandlerFunc]: - ... # noqa: WPS428, E704 + ) -> MessageHandlerDecorator: ... # noqa: WPS428, E704 def default_message_handler( # noqa: WPS320 self, diff --git a/pybotx/models/enums.py b/pybotx/models/enums.py index b8a4c446..05bc35fa 100644 --- a/pybotx/models/enums.py +++ b/pybotx/models/enums.py @@ -307,15 +307,13 @@ def convert_chat_type_from_domain(chat_type: ChatTypes) -> APIChatTypes: @overload def convert_chat_type_to_domain( chat_type: APIChatTypes, -) -> ChatTypes: - ... # noqa: WPS428, E704 +) -> ChatTypes: ... # noqa: WPS428, E704 @overload def convert_chat_type_to_domain( chat_type: str, -) -> UNSUPPORTED: - ... # noqa: WPS428, E704 +) -> UNSUPPORTED: ... # noqa: WPS428, E704 def convert_chat_type_to_domain( @@ -342,15 +340,13 @@ def convert_chat_type_to_domain( @overload def convert_sync_source_type_to_domain( sync_type: APISyncSourceTypes, -) -> SyncSourceTypes: - ... # noqa: WPS428, E704 +) -> SyncSourceTypes: ... # noqa: WPS428, E704 @overload def convert_sync_source_type_to_domain( sync_type: str, -) -> UNSUPPORTED: - ... # noqa: WPS428, E704 +) -> UNSUPPORTED: ... # noqa: WPS428, E704 def convert_sync_source_type_to_domain( diff --git a/setup.cfg b/setup.cfg index 6e87b6be..0463678d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -137,6 +137,7 @@ ignore = WPS603, # Forbidden `assert` S101, + E704, [tool:pytest] diff --git a/tests/test_handler_collector.py b/tests/test_handler_collector.py index 40304ece..727227f0 100644 --- a/tests/test_handler_collector.py +++ b/tests/test_handler_collector.py @@ -562,7 +562,6 @@ async def test__handler_collector__sync_smartapp_event__decorator__handler_alrea @collector.sync_smartapp_event async def duplicated_handle_sync_smartapp_event( *_: Any, - ) -> Any: - ... # noqa: E704 + ) -> Any: ... # noqa: E704 assert str(exc.value) == "Handler for sync smartapp event already registered" From 8ef78c9046184bc5729949770763cdad2d03d727 Mon Sep 17 00:00:00 2001 From: Aleksandr Osovskii Date: Wed, 14 May 2025 17:33:07 +0300 Subject: [PATCH 12/18] fix ci --- .github/workflows/python-app.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 14ddae9c..74d09617 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -20,7 +20,7 @@ jobs: env: BOT_CREDENTIALS: ${{ secrets.END_TO_END_TESTS_BOT_CREDENTIALS }} run: | - poetry run ./scripts/test --cov-report=xml + poetry run ./scripts/test --cov=pybotx --cov-report=xml - name: Upload coverage to Codecov uses: codecov/codecov-action@v2 From 81aadf9131471afcc2c86e5e4740fb0efe462b00 Mon Sep 17 00:00:00 2001 From: Aleksandr Osovskii Date: Wed, 14 May 2025 14:54:40 +0300 Subject: [PATCH 13/18] feat: dropped support for Python 3.8 and add Python 3.13 --- .github/workflows/python-app.yml | 4 +- README.md | 69 +- poetry.lock | 681 ++++++++++-------- pybotx/async_buffer.py | 23 +- pybotx/bot/callbacks/callback_manager.py | 6 +- pybotx/bot/callbacks/callback_repo_proto.py | 18 +- pybotx/bot/handler.py | 15 +- pybotx/bot/handler_collector.py | 11 +- pybotx/image_validators.py | 2 +- pybotx/models/async_files.py | 18 - pybotx/models/attachments.py | 32 +- pybotx/models/chats.py | 3 +- pybotx/models/enums.py | 14 +- pybotx/models/message/incoming_message.py | 3 - pyproject.toml | 48 +- setup.cfg | 1 + tests/client/test_botx_method.py | 2 +- tests/client/test_botx_method_callback.py | 2 +- tests/system_events/factories.py | 31 +- .../system_events/test_conference_changed.py | 13 +- tests/system_events/test_join_to_chat.py | 9 +- tests/test_base_command.py | 8 +- tests/test_handler_collector.py | 13 +- tests/test_middlewares.py | 11 +- 24 files changed, 561 insertions(+), 476 deletions(-) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index f4f88195..74d09617 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - python-version: ["3.9", "3.10", "3.11", "3.12"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] steps: - name: Setup dependencies @@ -20,7 +20,7 @@ jobs: env: BOT_CREDENTIALS: ${{ secrets.END_TO_END_TESTS_BOT_CREDENTIALS }} run: | - poetry run ./scripts/test --cov-report=xml + poetry run ./scripts/test --cov=pybotx --cov-report=xml - name: Upload coverage to Codecov uses: codecov/codecov-action@v2 diff --git a/README.md b/README.md index 7bfc0c0a..39673785 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ [![Coverage](https://codecov.io/gh/ExpressApp/pybotx/branch/master/graph/badge.svg)](https://codecov.io/gh/ExpressApp/pybotx/branch/master) [![Code style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black) + ## Особенности * Простая для использования @@ -15,6 +16,7 @@ * Полное покрытие тестами * Полное покрытие аннотациями типов + ## Установка Используя `poetry`: @@ -26,14 +28,15 @@ poetry add pybotx **Предупреждение:** Данный проект находится в активной разработке (`0.y.z`) и его API может быть изменён при повышении минорной версии. + ## Информация о мессенджере eXpress и платформе BotX -[Документация](https://docs.express.ms/) по мессенджеру (включая руководство пользователя и администратора). +Документацию по мессенджеру (включая руководство пользователя и администратора) +можно найти на [официальном сайте](https://express.ms/). Перед тем, как продолжать знакомство с библиотекой `pybotx`, -советуем прочитать данные -статьи: Что -такое [чат-боты](https://docs.express.ms/chatbots/developer-guide/#%D1%87%D0%B0%D1%82-%D0%B1%D0%BE%D1%82-%D0%B8-smartapp) +советуем прочитать данные статьи: Что такое [чат-боты] +(https://docs.express.ms/chatbots/developer-guide/#%D1%87%D0%B0%D1%82-%D0%B1%D0%BE%D1%82-%D0%B8-smartapp) и [SmartApp](https://docs.express.ms/smartapps/developer-guide/) и [Взаимодействие с Bot API и BotX API](https://docs.express.ms/chatbots/developer-guide/api/). В этих статьях находятся исчерпывающие примеры работы с платформой, которые @@ -42,6 +45,7 @@ poetry add pybotx Также не будет лишним ознакомиться с [документацией по плаформе BotX ](https://hackmd.ccsteam.ru/s/botx_platform). + ## Примеры готовых проектов на базе pybotx * [Next Feature Bot](https://github.com/ExpressApp/next-feature-bot) - бот, @@ -51,6 +55,7 @@ poetry add pybotx * [Weather SmartApp](https://github.com/ExpressApp/weather-smartapp) - приложение для просмотра погоды. + ## Минимальный пример бота (интеграция с FastAPI) ```python @@ -145,11 +150,11 @@ async def callback_handler(request: Request) -> JSONResponse: ## Примеры + ### Получение сообщений *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/api/bot-api/command/))* - ```python from uuid import UUID @@ -192,11 +197,11 @@ async def default_handler(_: IncomingMessage, bot: Bot) -> None: print("Hello from default handler") ``` + ### Получение системных событий *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/api/bot-api/command/#%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%BD%D1%8B%D0%B5-%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D1%8B))* - ```python from pybotx import * @@ -215,6 +220,7 @@ async def smartapp_event_handler(event: SmartAppEvent, bot: Bot) -> None: print(f"Got `smartapp_event` event: {event}") ``` + ### Получение синхронных SmartApp событий ```python @@ -226,7 +232,7 @@ collector = HandlerCollector() # Обработчик синхронных Smartapp событий, приходящих на эндпоинт `/smartapps/request` @collector.sync_smartapp_event async def handle_sync_smartapp_event( - event: SmartAppEvent, bot: Bot, + event: SmartAppEvent, bot: Bot, ) -> BotAPISyncSmartAppEventResultResponse: print(f"Got sync smartapp event: {event}") return BotAPISyncSmartAppEventResultResponse.from_domain( @@ -235,6 +241,7 @@ async def handle_sync_smartapp_event( ) ``` + ### Middlewares *(Этот функционал относится исключительно к `pybotx`)* @@ -248,9 +255,9 @@ collector = HandlerCollector() async def custom_api_client_middleware( - message: IncomingMessage, - bot: Bot, - call_next: IncomingMessageHandlerFunc, + message: IncomingMessage, + bot: Bot, + call_next: IncomingMessageHandlerFunc, ) -> None: # До вызова `call_next` (обязателен в каждой миддлвари) располагается # код, который выполняется до того, как сообщение дойдёт до @@ -292,18 +299,18 @@ ADMIN_HUIDS = (UUID("123e4567-e89b-12d3-a456-426614174000"),) async def request_id_middleware( - message: IncomingMessage, - bot: Bot, - call_next: IncomingMessageHandlerFunc, + message: IncomingMessage, + bot: Bot, + call_next: IncomingMessageHandlerFunc, ) -> None: message.state.request_id = uuid4() await call_next(message, bot) async def ensure_admin_middleware( - message: IncomingMessage, - bot: Bot, - call_next: IncomingMessageHandlerFunc, + message: IncomingMessage, + bot: Bot, + call_next: IncomingMessageHandlerFunc, ) -> None: if message.sender.huid not in ADMIN_HUIDS: await bot.answer_message("You are not admin") @@ -327,11 +334,11 @@ admin_collector = HandlerCollector(middlewares=[ensure_admin_middleware]) main_collector.include(admin_collector) ``` + ### Отправка сообщения *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D0%BE%D1%82%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B0-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D1%8F))* - ```python from uuid import UUID @@ -382,11 +389,11 @@ async def prebuild_answer_handler(message: IncomingMessage, bot: Bot) -> None: await bot.send(message=answer) ``` + #### Отправка сообщения с кнопками *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D0%BE%D1%82%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B0-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D1%8F-%D1%81-%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D0%B0%D0%BC%D0%B8))* - ```python from pybotx import * @@ -428,11 +435,11 @@ async def bubbles_handler(message: IncomingMessage, bot: Bot) -> None: ) ``` + #### Упоминание пользователя *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D1%83%D0%BF%D0%BE%D0%BC%D0%B8%D0%BD%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8F))* - ```python from pybotx import * @@ -455,11 +462,11 @@ async def echo_contact_handler(message: IncomingMessage, bot: Bot) -> None: await bot.answer_message(answer) ``` + #### Отправка файла в сообщении *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D0%BE%D1%82%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B0-%D1%84%D0%B0%D0%B9%D0%BB%D0%B0-%D0%B2-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B8))* - ```python from aiofiles.tempfile import NamedTemporaryFile @@ -494,7 +501,6 @@ async def echo_file_handler(message: IncomingMessage, bot: Bot) -> None: *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D1%80%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B9))* - ```python from pybotx import * @@ -533,7 +539,6 @@ async def increment_handler(message: IncomingMessage, bot: Bot) -> None: *([подробное описание функции]( https://hackmd.ccsteam.ru/s/E9MPeOxjP#%D0%A3%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D1%8F))* - ```python from pybotx import * @@ -558,6 +563,7 @@ async def deleted_message_handler(message: IncomingMessage, bot: Bot) -> None: await bot.answer_message("Self-deleted message", bubbles=bubbles) ``` + ### Обработчики ошибок *(Этот функционал относится исключительно к `pybotx`)* @@ -569,9 +575,9 @@ from pybotx import * async def internal_error_handler( - message: IncomingMessage, - bot: Bot, - exc: Exception, + message: IncomingMessage, + bot: Bot, + exc: Exception, ) -> None: logger.exception("Internal error:") @@ -593,7 +599,6 @@ bot = Bot( *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5-%D1%87%D0%B0%D1%82%D0%B0))* - ```python from pybotx import * @@ -625,7 +630,6 @@ async def create_group_chat_handler(message: IncomingMessage, bot: Bot) -> None: *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D0%BF%D0%BE%D0%B8%D1%81%D0%BA-%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8F))* - ```python import dataclasses @@ -652,7 +656,6 @@ async def search_user_handler(message: IncomingMessage, bot: Bot) -> None: *([подробное описание функции]( https://docs.express.ms/chatbots/developer-guide/development-and-debugging/examples/#%D0%BF%D0%BE%D0%BB%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D0%BF%D0%B8%D1%81%D0%BA%D0%B0-%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B5%D0%B9-%D0%BD%D0%B0-cts))* - ```python from pybotx import * @@ -662,11 +665,11 @@ collector = HandlerCollector() @collector.command("/get_users_list", description="Get a list of users") async def users_list_handler(message: IncomingMessage, bot: Bot) -> None: async with bot.users_as_csv( - bot_id=message.bot.id, - cts_user=True, - unregistered=False, - botx=False, + bot_id=message.bot.id, + cts_user=True, + unregistered=False, + botx=False, ) as users: async for user in users: print(user) -``` +``` \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 3ac3d5c2..0eb11c13 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,14 +2,14 @@ [[package]] name = "add-trailing-comma" -version = "2.2.1" +version = "3.1.0" description = "Automatically add trailing commas to calls and literals" optional = false -python-versions = ">=3.6.1" +python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "add_trailing_comma-2.2.1-py2.py3-none-any.whl", hash = "sha256:981c18282b38ec5bceab80ef11485440334d2a274fcf3fce1f91692374b6d818"}, - {file = "add_trailing_comma-2.2.1.tar.gz", hash = "sha256:1640e97c4e85132633a6cb19b29e392dbaf9516292388afa685f7ef1012468e0"}, + {file = "add_trailing_comma-3.1.0-py2.py3-none-any.whl", hash = "sha256:160207e2ac414a841a71f4f5095f7350f87af460aab3dfe36cfa037992530e5c"}, + {file = "add_trailing_comma-3.1.0.tar.gz", hash = "sha256:b255319d7ef6dca308b051ffd80fccf98c018879744c7c7e03083b2eee079c45"}, ] [package.dependencies] @@ -85,24 +85,6 @@ doc = ["Sphinx (>=8.2,<9.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", test = ["anyio[trio]", "blockbuster (>=1.5.23)", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\" and python_version < \"3.14\""] trio = ["trio (>=0.26.1)"] -[[package]] -name = "asgiref" -version = "3.8.1" -description = "ASGI specs, helper code, and adapters" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47"}, - {file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"}, -] - -[package.dependencies] -typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""} - -[package.extras] -tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] - [[package]] name = "astor" version = "0.8.1" @@ -137,87 +119,89 @@ tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" a [[package]] name = "autoflake" -version = "1.7.8" +version = "2.3.1" description = "Removes unused imports and unused variables" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "autoflake-1.7.8-py3-none-any.whl", hash = "sha256:46373ef69b6714f5064c923bb28bd797c4f8a9497f557d87fc36665c6d956b39"}, - {file = "autoflake-1.7.8.tar.gz", hash = "sha256:e7e46372dee46fa1c97acf310d99d922b63d369718a270809d7c278d34a194cf"}, + {file = "autoflake-2.3.1-py3-none-any.whl", hash = "sha256:3ae7495db9084b7b32818b4140e6dc4fc280b712fb414f5b8fe57b0a8e85a840"}, + {file = "autoflake-2.3.1.tar.gz", hash = "sha256:c98b75dc5b0a86459c4f01a1d32ac7eb4338ec4317a4469515ff1e687ecd909e"}, ] [package.dependencies] -pyflakes = ">=1.1.0,<3" +pyflakes = ">=3.0.0" tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} [[package]] name = "bandit" -version = "1.7.2" +version = "1.8.3" description = "Security oriented static analyser for python code." optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "bandit-1.7.2-py3-none-any.whl", hash = "sha256:e20402cadfd126d85b68ed4c8862959663c8c372dbbb1fca8f8e2c9f55a067ec"}, - {file = "bandit-1.7.2.tar.gz", hash = "sha256:6d11adea0214a43813887bfe71a377b5a9955e4c826c8ffd341b494e3ab25260"}, + {file = "bandit-1.8.3-py3-none-any.whl", hash = "sha256:28f04dc0d258e1dd0f99dee8eefa13d1cb5e3fde1a5ab0c523971f97b289bcd8"}, + {file = "bandit-1.8.3.tar.gz", hash = "sha256:f5847beb654d309422985c36644649924e0ea4425c76dec2e89110b87506193a"}, ] [package.dependencies] colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} -GitPython = ">=1.0.1" PyYAML = ">=5.3.1" +rich = "*" stevedore = ">=1.20.0" [package.extras] -test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "toml"] -toml = ["toml"] +baseline = ["GitPython (>=3.1.30)"] +sarif = ["jschema-to-python (>=1.2.3)", "sarif-om (>=1.0.4)"] +test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)"] +toml = ["tomli (>=1.1.0) ; python_version < \"3.11\""] yaml = ["PyYAML"] [[package]] name = "black" -version = "22.3.0" +version = "25.1.0" description = "The uncompromising code formatter." optional = false -python-versions = ">=3.6.2" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "black-22.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09"}, - {file = "black-22.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb"}, - {file = "black-22.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a"}, - {file = "black-22.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968"}, - {file = "black-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d"}, - {file = "black-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cc1e1de68c8e5444e8f94c3670bb48a2beef0e91dddfd4fcc29595ebd90bb9ce"}, - {file = "black-22.3.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2fc92002d44746d3e7db7cf9313cf4452f43e9ea77a2c939defce3b10b5c82"}, - {file = "black-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:a6342964b43a99dbc72f72812bf88cad8f0217ae9acb47c0d4f141a6416d2d7b"}, - {file = "black-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:328efc0cc70ccb23429d6be184a15ce613f676bdfc85e5fe8ea2a9354b4e9015"}, - {file = "black-22.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06f9d8846f2340dfac80ceb20200ea5d1b3f181dd0556b47af4e8e0b24fa0a6b"}, - {file = "black-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4efa5fad66b903b4a5f96d91461d90b9507a812b3c5de657d544215bb7877a"}, - {file = "black-22.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8477ec6bbfe0312c128e74644ac8a02ca06bcdb8982d4ee06f209be28cdf163"}, - {file = "black-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:637a4014c63fbf42a692d22b55d8ad6968a946b4a6ebc385c5505d9625b6a464"}, - {file = "black-22.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:863714200ada56cbc366dc9ae5291ceb936573155f8bf8e9de92aef51f3ad0f0"}, - {file = "black-22.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10dbe6e6d2988049b4655b2b739f98785a884d4d6b85bc35133a8fb9a2233176"}, - {file = "black-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:cee3e11161dde1b2a33a904b850b0899e0424cc331b7295f2a9698e79f9a69a0"}, - {file = "black-22.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20"}, - {file = "black-22.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a"}, - {file = "black-22.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad"}, - {file = "black-22.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21"}, - {file = "black-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265"}, - {file = "black-22.3.0-py3-none-any.whl", hash = "sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72"}, - {file = "black-22.3.0.tar.gz", hash = "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79"}, + {file = "black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32"}, + {file = "black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da"}, + {file = "black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7"}, + {file = "black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9"}, + {file = "black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0"}, + {file = "black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299"}, + {file = "black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096"}, + {file = "black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2"}, + {file = "black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b"}, + {file = "black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc"}, + {file = "black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f"}, + {file = "black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba"}, + {file = "black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f"}, + {file = "black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3"}, + {file = "black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171"}, + {file = "black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18"}, + {file = "black-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0"}, + {file = "black-25.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f"}, + {file = "black-25.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e"}, + {file = "black-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355"}, + {file = "black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717"}, + {file = "black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666"}, ] [package.dependencies] click = ">=8.0.0" mypy-extensions = ">=0.4.3" +packaging = ">=22.0" pathspec = ">=0.9.0" platformdirs = ">=2" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} +typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] +d = ["aiohttp (>=3.10)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] @@ -454,6 +438,30 @@ files = [ {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"}, ] +[[package]] +name = "deepdiff" +version = "8.5.0" +description = "Deep Difference and Search of any Python object/data. Recreate objects by adding adding deltas to each other." +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "deepdiff-8.5.0-py3-none-any.whl", hash = "sha256:d4599db637f36a1c285f5fdfc2cd8d38bde8d8be8636b65ab5e425b67c54df26"}, + {file = "deepdiff-8.5.0.tar.gz", hash = "sha256:a4dd3529fa8d4cd5b9cbb6e3ea9c95997eaa919ba37dac3966c1b8f872dc1cd1"}, +] + +[package.dependencies] +orderly-set = ">=5.4.1,<6" + +[package.extras] +cli = ["click (>=8.1.0,<8.2.0)", "pyyaml (>=6.0.0,<6.1.0)"] +coverage = ["coverage (>=7.6.0,<7.7.0)"] +dev = ["bump2version (>=1.0.0,<1.1.0)", "ipdb (>=0.13.0,<0.14.0)", "jsonpickle (>=4.0.0,<4.1.0)", "nox (==2025.5.1)", "numpy (>=2.0,<3.0) ; python_version < \"3.10\"", "numpy (>=2.2.0,<2.3.0) ; python_version >= \"3.10\"", "orjson (>=3.10.0,<3.11.0)", "pandas (>=2.2.0,<2.3.0)", "polars (>=1.21.0,<1.22.0)", "python-dateutil (>=2.9.0,<2.10.0)", "tomli (>=2.2.0,<2.3.0)", "tomli-w (>=1.2.0,<1.3.0)"] +docs = ["Sphinx (>=6.2.0,<6.3.0)", "sphinx-sitemap (>=2.6.0,<2.7.0)", "sphinxemoji (>=0.3.0,<0.4.0)"] +optimize = ["orjson"] +static = ["flake8 (>=7.1.0,<7.2.0)", "flake8-pyproject (>=1.2.3,<1.3.0)", "pydantic (>=2.10.0,<2.11.0)"] +test = ["pytest (>=8.3.0,<8.4.0)", "pytest-benchmark (>=5.1.0,<5.2.0)", "pytest-cov (>=6.0.0,<6.1.0)", "python-dotenv (>=1.0.0,<1.1.0)"] + [[package]] name = "docutils" version = "0.21.2" @@ -497,95 +505,127 @@ typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} [package.extras] test = ["pytest (>=6)"] +[[package]] +name = "factory-boy" +version = "3.3.3" +description = "A versatile test fixtures replacement based on thoughtbot's factory_bot for Ruby." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "factory_boy-3.3.3-py2.py3-none-any.whl", hash = "sha256:1c39e3289f7e667c4285433f305f8d506efc2fe9c73aaea4151ebd5cdea394fc"}, + {file = "factory_boy-3.3.3.tar.gz", hash = "sha256:866862d226128dfac7f2b4160287e899daf54f2612778327dd03d0e2cb1e3d03"}, +] + +[package.dependencies] +Faker = ">=0.7.0" + +[package.extras] +dev = ["Django", "Pillow", "SQLAlchemy", "coverage", "flake8", "isort", "mongoengine", "mongomock", "mypy", "tox", "wheel (>=0.32.0)", "zest.releaser[recommended]"] +doc = ["Sphinx", "sphinx-rtd-theme", "sphinxcontrib-spelling"] + +[[package]] +name = "faker" +version = "37.1.0" +description = "Faker is a Python package that generates fake data for you." +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "faker-37.1.0-py3-none-any.whl", hash = "sha256:dc2f730be71cb770e9c715b13374d80dbcee879675121ab51f9683d262ae9a1c"}, + {file = "faker-37.1.0.tar.gz", hash = "sha256:ad9dc66a3b84888b837ca729e85299a96b58fdaef0323ed0baace93c9614af06"}, +] + +[package.dependencies] +tzdata = "*" + [[package]] name = "fastapi" -version = "0.95.2" +version = "0.115.12" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "fastapi-0.95.2-py3-none-any.whl", hash = "sha256:d374dbc4ef2ad9b803899bd3360d34c534adc574546e25314ab72c0c4411749f"}, - {file = "fastapi-0.95.2.tar.gz", hash = "sha256:4d9d3e8c71c73f11874bcf5e33626258d143252e329a01002f767306c64fb982"}, + {file = "fastapi-0.115.12-py3-none-any.whl", hash = "sha256:e94613d6c05e27be7ffebdd6ea5f388112e5e430c8f7d6494a9d1d88d43e814d"}, + {file = "fastapi-0.115.12.tar.gz", hash = "sha256:1e2c2a2646905f9e83d32f04a3f86aff4a286669c6c950ca95b5fd68c2602681"}, ] [package.dependencies] -pydantic = ">=1.6.2,<1.7 || >1.7,<1.7.1 || >1.7.1,<1.7.2 || >1.7.2,<1.7.3 || >1.7.3,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0" -starlette = ">=0.27.0,<0.28.0" +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" +starlette = ">=0.40.0,<0.47.0" +typing-extensions = ">=4.8.0" [package.extras] -all = ["email-validator (>=1.1.1)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "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)"] -dev = ["pre-commit (>=2.17.0,<3.0.0)", "ruff (==0.0.138)", "uvicorn[standard] (>=0.12.0,<0.21.0)"] -doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pyyaml (>=5.3.1,<7.0.0)", "typer-cli (>=0.0.13,<0.0.14)", "typer[all] (>=0.6.1,<0.8.0)"] -test = ["anyio[trio] (>=3.2.1,<4.0.0)", "black (==23.1.0)", "coverage[toml] (>=6.5.0,<8.0)", "databases[sqlite] (>=0.3.2,<0.7.0)", "email-validator (>=1.1.1,<2.0.0)", "flask (>=1.1.2,<3.0.0)", "httpx (>=0.23.0,<0.24.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.982)", "orjson (>=3.2.1,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "peewee (>=3.13.3,<4.0.0)", "pytest (>=7.1.3,<8.0.0)", "python-jose[cryptography] (>=3.3.0,<4.0.0)", "python-multipart (>=0.0.5,<0.0.7)", "pyyaml (>=5.3.1,<7.0.0)", "ruff (==0.0.138)", "sqlalchemy (>=1.3.18,<1.4.43)", "types-orjson (==3.6.2)", "types-ujson (==5.7.0.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)"] +all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=3.1.5)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "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)"] +standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=3.1.5)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"] [[package]] name = "flake8" -version = "4.0.1" +version = "7.2.0" description = "the modular source code checker: pep8 pyflakes and co" optional = false -python-versions = ">=3.6" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, - {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, + {file = "flake8-7.2.0-py2.py3-none-any.whl", hash = "sha256:93b92ba5bdb60754a6da14fa3b93a9361fd00a59632ada61fd7b130436c40343"}, + {file = "flake8-7.2.0.tar.gz", hash = "sha256:fa558ae3f6f7dbf2b4f22663e5343b6b6023620461f8d4ff2019ef4b5ee70426"}, ] [package.dependencies] -mccabe = ">=0.6.0,<0.7.0" -pycodestyle = ">=2.8.0,<2.9.0" -pyflakes = ">=2.4.0,<2.5.0" +mccabe = ">=0.7.0,<0.8.0" +pycodestyle = ">=2.13.0,<2.14.0" +pyflakes = ">=3.3.0,<3.4.0" [[package]] name = "flake8-bandit" -version = "2.1.2" +version = "4.1.1" description = "Automated security testing with bandit and flake8." optional = false -python-versions = "*" +python-versions = ">=3.6" groups = ["dev"] files = [ - {file = "flake8_bandit-2.1.2.tar.gz", hash = "sha256:687fc8da2e4a239b206af2e54a90093572a60d0954f3054e23690739b0b0de3b"}, + {file = "flake8_bandit-4.1.1-py3-none-any.whl", hash = "sha256:4c8a53eb48f23d4ef1e59293657181a3c989d0077c9952717e98a0eace43e06d"}, + {file = "flake8_bandit-4.1.1.tar.gz", hash = "sha256:068e09287189cbfd7f986e92605adea2067630b75380c6b5733dab7d87f9a84e"}, ] [package.dependencies] -bandit = "*" -flake8 = "*" -flake8-polyfill = "*" -pycodestyle = "*" +bandit = ">=1.7.3" +flake8 = ">=5.0.0" [[package]] name = "flake8-broken-line" -version = "0.4.0" +version = "1.0.0" description = "Flake8 plugin to forbid backslashes for line breaks" optional = false -python-versions = ">=3.6,<4.0" +python-versions = ">=3.8,<4.0" groups = ["dev"] files = [ - {file = "flake8-broken-line-0.4.0.tar.gz", hash = "sha256:771aab5aa0997666796fed249d0e48e6c01cdfeca8c95521eea28a38b7ced4c7"}, - {file = "flake8_broken_line-0.4.0-py3-none-any.whl", hash = "sha256:e9c522856862239a2c7ef2c1de0276fa598572aa864bd4e9c7efc2a827538515"}, + {file = "flake8_broken_line-1.0.0-py3-none-any.whl", hash = "sha256:96c964336024a5030dc536a9f6fb02aa679e2d2a6b35b80a558b5136c35832a9"}, + {file = "flake8_broken_line-1.0.0.tar.gz", hash = "sha256:e2c6a17f8d9a129e99c1320fce89b33843e2963871025c4c2bb7b8b8d8732a85"}, ] [package.dependencies] -flake8 = ">=3.5,<5" +flake8 = ">5" [[package]] name = "flake8-bugbear" -version = "21.11.29" +version = "24.12.12" description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." optional = false -python-versions = ">=3.6" +python-versions = ">=3.8.1" groups = ["dev"] files = [ - {file = "flake8-bugbear-21.11.29.tar.gz", hash = "sha256:8b04cb2fafc6a78e1a9d873bd3988e4282f7959bb6b0d7c1ae648ec09b937a7b"}, - {file = "flake8_bugbear-21.11.29-py36.py37.py38-none-any.whl", hash = "sha256:179e41ddae5de5e3c20d1f61736feeb234e70958fbb56ab3c28a67739c8e9a82"}, + {file = "flake8_bugbear-24.12.12-py3-none-any.whl", hash = "sha256:1b6967436f65ca22a42e5373aaa6f2d87966ade9aa38d4baf2a1be550767545e"}, + {file = "flake8_bugbear-24.12.12.tar.gz", hash = "sha256:46273cef0a6b6ff48ca2d69e472f41420a42a46e24b2a8972e4f0d6733d12a64"}, ] [package.dependencies] -attrs = ">=19.2.0" -flake8 = ">=3.0.0" +attrs = ">=22.2.0" +flake8 = ">=6.0.0" [package.extras] -dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit"] +dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "pytest", "tox"] [[package]] name = "flake8-commas" @@ -651,54 +691,39 @@ pydocstyle = ">=2.1" [[package]] name = "flake8-eradicate" -version = "1.4.0" +version = "1.5.0" description = "Flake8 plugin to find commented out code" optional = false -python-versions = ">=3.7,<4.0" +python-versions = ">=3.8,<4.0" groups = ["dev"] files = [ - {file = "flake8-eradicate-1.4.0.tar.gz", hash = "sha256:3088cfd6717d1c9c6c3ac45ef2e5f5b6c7267f7504d5a74b781500e95cb9c7e1"}, - {file = "flake8_eradicate-1.4.0-py3-none-any.whl", hash = "sha256:e3bbd0871be358e908053c1ab728903c114f062ba596b4d40c852fd18f473d56"}, + {file = "flake8_eradicate-1.5.0-py3-none-any.whl", hash = "sha256:18acc922ad7de623f5247c7d5595da068525ec5437dd53b22ec2259b96ce9d22"}, + {file = "flake8_eradicate-1.5.0.tar.gz", hash = "sha256:aee636cb9ecb5594a7cd92d67ad73eb69909e5cc7bd81710cf9d00970f3983a6"}, ] [package.dependencies] attrs = "*" eradicate = ">=2.0,<3.0" -flake8 = ">=3.5,<6" +flake8 = ">5" [[package]] name = "flake8-isort" -version = "4.2.0" -description = "flake8 plugin that integrates isort ." +version = "6.1.2" +description = "flake8 plugin that integrates isort" optional = false -python-versions = "*" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "flake8-isort-4.2.0.tar.gz", hash = "sha256:26571500cd54976bbc0cf1006ffbcd1a68dd102f816b7a1051b219616ba9fee0"}, - {file = "flake8_isort-4.2.0-py3-none-any.whl", hash = "sha256:5b87630fb3719bf4c1833fd11e0d9534f43efdeba524863e15d8f14a7ef6adbf"}, + {file = "flake8_isort-6.1.2-py3-none-any.whl", hash = "sha256:549197dedf0273502fb74f04c080beed9e62a7eb70244610413d27052e78bd3b"}, + {file = "flake8_isort-6.1.2.tar.gz", hash = "sha256:9d0452acdf0e1cd6f2d6848e3605e66b54d920e73471fb4744eef0f93df62d5d"}, ] [package.dependencies] -flake8 = ">=3.2.1,<6" -isort = ">=4.3.5,<6" +flake8 = "*" +isort = ">=5.0.0,<7" [package.extras] -test = ["pytest-cov"] - -[[package]] -name = "flake8-polyfill" -version = "1.0.2" -description = "Polyfill package for Flake8 plugins" -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "flake8-polyfill-1.0.2.tar.gz", hash = "sha256:e44b087597f6da52ec6393a709e7108b2905317d0c0b744cdca6208e670d8eda"}, - {file = "flake8_polyfill-1.0.2-py2.py3-none-any.whl", hash = "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9"}, -] - -[package.dependencies] -flake8 = "*" +test = ["pytest"] [[package]] name = "flake8-quotes" @@ -717,20 +742,23 @@ setuptools = "*" [[package]] name = "flake8-rst-docstrings" -version = "0.2.7" -description = "Python docstring reStructuredText (RST) validator" +version = "0.3.1" +description = "Python docstring reStructuredText (RST) validator for flake8" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "flake8-rst-docstrings-0.2.7.tar.gz", hash = "sha256:2740067ab9237559dd45a3434d8c987792c7b259ca563621a3b95efe201f5382"}, - {file = "flake8_rst_docstrings-0.2.7-py3-none-any.whl", hash = "sha256:5d56075dce360bcc9c6775bfe7cb431aa395de600ca7e8d40580a28d50b2a803"}, + {file = "flake8_rst_docstrings-0.3.1-py3-none-any.whl", hash = "sha256:ed831afca7ee47851e2162d5fa726b823b446fd46085c2164d7979ae5d9a96d7"}, + {file = "flake8_rst_docstrings-0.3.1.tar.gz", hash = "sha256:26dcc1338caf985990677696a8a6a274f73a0c6845b85f567befd3b648db78e2"}, ] [package.dependencies] -flake8 = ">=3.0.0" +flake8 = ">=3" pygments = "*" -restructuredtext-lint = "*" +restructuredtext_lint = "*" + +[package.extras] +develop = ["build", "twine"] [[package]] name = "flake8-string-format" @@ -747,40 +775,6 @@ files = [ [package.dependencies] flake8 = "*" -[[package]] -name = "gitdb" -version = "4.0.12" -description = "Git Object Database" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf"}, - {file = "gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571"}, -] - -[package.dependencies] -smmap = ">=3.0.1,<6" - -[[package]] -name = "gitpython" -version = "3.1.44" -description = "GitPython is a Python library used to interact with Git repositories" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "GitPython-3.1.44-py3-none-any.whl", hash = "sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110"}, - {file = "gitpython-3.1.44.tar.gz", hash = "sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269"}, -] - -[package.dependencies] -gitdb = ">=4.0.1,<5" - -[package.extras] -doc = ["sphinx (>=7.1.2,<7.2)", "sphinx-autodoc-typehints", "sphinx_rtd_theme"] -test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock ; python_version < \"3.8\"", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions ; python_version < \"3.11\""] - [[package]] name = "h11" version = "0.16.0" @@ -817,14 +811,14 @@ trio = ["trio (>=0.22.0,<1.0)"] [[package]] name = "httpx" -version = "0.25.2" +version = "0.28.1" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" groups = ["main", "dev"] files = [ - {file = "httpx-0.25.2-py3-none-any.whl", hash = "sha256:a05d3d052d9b2dfce0e3896636467f8a5342fb2b902c819428e1ac65413ca118"}, - {file = "httpx-0.25.2.tar.gz", hash = "sha256:8b8fcaa0c8ea7b05edd69a094e63a2094c4efcb48129fb757361bc423c0ad9e8"}, + {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, + {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, ] [package.dependencies] @@ -832,13 +826,13 @@ anyio = "*" certifi = "*" httpcore = "==1.*" idna = "*" -sniffio = "*" [package.extras] brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] +zstd = ["zstandard (>=0.18.0)"] [[package]] name = "idna" @@ -869,21 +863,19 @@ files = [ [[package]] name = "isort" -version = "5.10.1" +version = "6.0.1" description = "A Python utility / library to sort Python imports." optional = false -python-versions = ">=3.6.1,<4.0" +python-versions = ">=3.9.0" groups = ["dev"] files = [ - {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, - {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, + {file = "isort-6.0.1-py3-none-any.whl", hash = "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615"}, + {file = "isort-6.0.1.tar.gz", hash = "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450"}, ] [package.extras] -colors = ["colorama (>=0.4.3,<0.5.0)"] -pipfile-deprecated-finder = ["pipreqs", "requirementslib"] +colors = ["colorama"] plugins = ["setuptools"] -requirements-deprecated-finder = ["pip-api", "pipreqs"] [[package]] name = "loguru" @@ -904,69 +896,131 @@ win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} [package.extras] dev = ["Sphinx (>=4.1.1) ; python_version >= \"3.6\"", "black (>=19.10b0) ; python_version >= \"3.6\"", "colorama (>=0.3.4)", "docutils (==0.16)", "flake8 (>=3.7.7)", "isort (>=5.1.1) ; python_version >= \"3.6\"", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "sphinx-autobuild (>=0.7.1) ; python_version >= \"3.6\"", "sphinx-rtd-theme (>=0.4.3) ; python_version >= \"3.6\"", "tox (>=3.9.0)"] +[[package]] +name = "markdown-it-py" +version = "3.0.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, +] + +[package.dependencies] +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins"] +profiling = ["gprof2dot"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + [[package]] name = "mccabe" -version = "0.6.1" +version = "0.7.0" description = "McCabe checker, plugin for flake8" optional = false -python-versions = "*" +python-versions = ">=3.6" groups = ["dev"] files = [ - {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, - {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, ] [[package]] name = "mypy" -version = "0.910" +version = "1.15.0" description = "Optional static typing for Python" optional = false -python-versions = ">=3.5" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "mypy-0.910-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:a155d80ea6cee511a3694b108c4494a39f42de11ee4e61e72bc424c490e46457"}, - {file = "mypy-0.910-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b94e4b785e304a04ea0828759172a15add27088520dc7e49ceade7834275bedb"}, - {file = "mypy-0.910-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:088cd9c7904b4ad80bec811053272986611b84221835e079be5bcad029e79dd9"}, - {file = "mypy-0.910-cp35-cp35m-win_amd64.whl", hash = "sha256:adaeee09bfde366d2c13fe6093a7df5df83c9a2ba98638c7d76b010694db760e"}, - {file = "mypy-0.910-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ecd2c3fe726758037234c93df7e98deb257fd15c24c9180dacf1ef829da5f921"}, - {file = "mypy-0.910-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d9dd839eb0dc1bbe866a288ba3c1afc33a202015d2ad83b31e875b5905a079b6"}, - {file = "mypy-0.910-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:3e382b29f8e0ccf19a2df2b29a167591245df90c0b5a2542249873b5c1d78212"}, - {file = "mypy-0.910-cp36-cp36m-win_amd64.whl", hash = "sha256:53fd2eb27a8ee2892614370896956af2ff61254c275aaee4c230ae771cadd885"}, - {file = "mypy-0.910-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b6fb13123aeef4a3abbcfd7e71773ff3ff1526a7d3dc538f3929a49b42be03f0"}, - {file = "mypy-0.910-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e4dab234478e3bd3ce83bac4193b2ecd9cf94e720ddd95ce69840273bf44f6de"}, - {file = "mypy-0.910-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:7df1ead20c81371ccd6091fa3e2878559b5c4d4caadaf1a484cf88d93ca06703"}, - {file = "mypy-0.910-cp37-cp37m-win_amd64.whl", hash = "sha256:0aadfb2d3935988ec3815952e44058a3100499f5be5b28c34ac9d79f002a4a9a"}, - {file = "mypy-0.910-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ec4e0cd079db280b6bdabdc807047ff3e199f334050db5cbb91ba3e959a67504"}, - {file = "mypy-0.910-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:119bed3832d961f3a880787bf621634ba042cb8dc850a7429f643508eeac97b9"}, - {file = "mypy-0.910-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:866c41f28cee548475f146aa4d39a51cf3b6a84246969f3759cb3e9c742fc072"}, - {file = "mypy-0.910-cp38-cp38-win_amd64.whl", hash = "sha256:ceb6e0a6e27fb364fb3853389607cf7eb3a126ad335790fa1e14ed02fba50811"}, - {file = "mypy-0.910-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a85e280d4d217150ce8cb1a6dddffd14e753a4e0c3cf90baabb32cefa41b59e"}, - {file = "mypy-0.910-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:42c266ced41b65ed40a282c575705325fa7991af370036d3f134518336636f5b"}, - {file = "mypy-0.910-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:3c4b8ca36877fc75339253721f69603a9c7fdb5d4d5a95a1a1b899d8b86a4de2"}, - {file = "mypy-0.910-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:c0df2d30ed496a08de5daed2a9ea807d07c21ae0ab23acf541ab88c24b26ab97"}, - {file = "mypy-0.910-cp39-cp39-win_amd64.whl", hash = "sha256:c6c2602dffb74867498f86e6129fd52a2770c48b7cd3ece77ada4fa38f94eba8"}, - {file = "mypy-0.910-py3-none-any.whl", hash = "sha256:ef565033fa5a958e62796867b1df10c40263ea9ded87164d67572834e57a174d"}, - {file = "mypy-0.910.tar.gz", hash = "sha256:704098302473cb31a218f1775a873b376b30b4c18229421e9e9dc8916fd16150"}, + {file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, + {file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, + {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"}, + {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"}, + {file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"}, + {file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"}, + {file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}, + {file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}, + {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}, + {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}, + {file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}, + {file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}, + {file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"}, + {file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"}, + {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"}, + {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}, + {file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}, + {file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}, + {file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"}, + {file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"}, + {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"}, + {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"}, + {file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"}, + {file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"}, + {file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"}, + {file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"}, + {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"}, + {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"}, + {file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"}, + {file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"}, + {file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}, + {file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"}, ] [package.dependencies] -mypy-extensions = ">=0.4.3,<0.5.0" -toml = "*" -typing-extensions = ">=3.7.4" +mypy_extensions = ">=1.0.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing_extensions = ">=4.6.0" [package.extras] dmypy = ["psutil (>=4.0)"] -python2 = ["typed-ast (>=1.4.0,<1.5.0)"] +faster-cache = ["orjson"] +install-types = ["pip"] +mypyc = ["setuptools (>=50)"] +reports = ["lxml"] [[package]] name = "mypy-extensions" -version = "0.4.4" -description = "Experimental type system extensions for programs checked with the mypy typechecker." +version = "1.1.0" +description = "Type system extensions for programs checked with the mypy type checker." optional = false -python-versions = ">=2.7" +python-versions = ">=3.8" groups = ["main", "dev"] files = [ - {file = "mypy_extensions-0.4.4.tar.gz", hash = "sha256:c8b707883a96efe9b4bb3aaf0dcc07e7e217d7d8368eec4db4049ee9e142f4fd"}, + {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, + {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, +] + +[[package]] +name = "orderly-set" +version = "5.4.1" +description = "Orderly set" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "orderly_set-5.4.1-py3-none-any.whl", hash = "sha256:b5e21d21680bd9ef456885db800c5cb4f76a03879880c0175e1b077fb166fd83"}, + {file = "orderly_set-5.4.1.tar.gz", hash = "sha256:a1fb5a4fdc5e234e9e8d8e5c1bbdbc4540f4dfe50d12bf17c8bc5dbf1c9c878d"}, ] [[package]] @@ -1010,19 +1064,18 @@ setuptools = "*" [[package]] name = "pep8-naming" -version = "0.12.1" +version = "0.13.3" description = "Check PEP-8 naming conventions, plugin for flake8" optional = false -python-versions = "*" +python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "pep8-naming-0.12.1.tar.gz", hash = "sha256:bb2455947757d162aa4cad55dba4ce029005cd1692f2899a21d51d8630ca7841"}, - {file = "pep8_naming-0.12.1-py2.py3-none-any.whl", hash = "sha256:4a8daeaeb33cfcde779309fc0c9c0a68a3bbe2ad8a8308b763c5068f86eb9f37"}, + {file = "pep8-naming-0.13.3.tar.gz", hash = "sha256:1705f046dfcd851378aac3be1cd1551c7c1e5ff363bacad707d43007877fa971"}, + {file = "pep8_naming-0.13.3-py3-none-any.whl", hash = "sha256:1a86b8c71a03337c97181917e2b472f0f5e4ccb06844a0d6f0a33522549e7a80"}, ] [package.dependencies] -flake8 = ">=3.9.1" -flake8-polyfill = ">=1.0.2,<2" +flake8 = ">=5.0.0" [[package]] name = "platformdirs" @@ -1059,14 +1112,14 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pycodestyle" -version = "2.8.0" +version = "2.13.0" description = "Python style guide checker" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, - {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, + {file = "pycodestyle-2.13.0-py2.py3-none-any.whl", hash = "sha256:35863c5974a271c7a726ed228a14a4f6daf49df369d8c50cd9a6f58a5e143ba9"}, + {file = "pycodestyle-2.13.0.tar.gz", hash = "sha256:c8415bf09abe81d9c7f872502a6eee881fbe85d8763dd5b9924bb0a01d67efae"}, ] [[package]] @@ -1156,14 +1209,14 @@ toml = ["tomli (>=1.2.3) ; python_version < \"3.11\""] [[package]] name = "pyflakes" -version = "2.4.0" +version = "3.3.2" description = "passive checker of Python programs" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, - {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, + {file = "pyflakes-3.3.2-py2.py3-none-any.whl", hash = "sha256:5039c8339cbb1944045f4ee5466908906180f13cc99cc9949348d10f82a5c32a"}, + {file = "pyflakes-3.3.2.tar.gz", hash = "sha256:6dfd61d87b97fba5dcfaaf781171ac16be16453be6d816147989e7f6e6a9576b"}, ] [[package]] @@ -1201,64 +1254,65 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] [[package]] name = "pytest" -version = "7.2.0" +version = "8.3.5" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, - {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, + {file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"}, + {file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"}, ] [package.dependencies] -attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=0.12,<2.0" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} +pluggy = ">=1.5,<2" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-asyncio" -version = "0.16.0" -description = "Pytest support for asyncio." +version = "0.26.0" +description = "Pytest support for asyncio" optional = false -python-versions = ">= 3.6" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "pytest-asyncio-0.16.0.tar.gz", hash = "sha256:7496c5977ce88c34379df64a66459fe395cd05543f0a2f837016e7144391fcfb"}, - {file = "pytest_asyncio-0.16.0-py3-none-any.whl", hash = "sha256:5f2a21273c47b331ae6aa5b36087047b4899e40f03f18397c0e65fa5cca54e9b"}, + {file = "pytest_asyncio-0.26.0-py3-none-any.whl", hash = "sha256:7b51ed894f4fbea1340262bdae5135797ebbe21d8638978e35d31c6d19f72fb0"}, + {file = "pytest_asyncio-0.26.0.tar.gz", hash = "sha256:c4df2a697648241ff39e7f0e4a73050b03f123f760673956cf0d72a4990e312f"}, ] [package.dependencies] -pytest = ">=5.4.0" +pytest = ">=8.2,<9" +typing-extensions = {version = ">=4.12", markers = "python_version < \"3.10\""} [package.extras] -testing = ["coverage", "hypothesis (>=5.7.1)"] +docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1)"] +testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] [[package]] name = "pytest-cov" -version = "4.0.0" +version = "6.1.1" description = "Pytest plugin for measuring coverage." optional = false -python-versions = ">=3.6" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "pytest-cov-4.0.0.tar.gz", hash = "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"}, - {file = "pytest_cov-4.0.0-py3-none-any.whl", hash = "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b"}, + {file = "pytest_cov-6.1.1-py3-none-any.whl", hash = "sha256:bddf29ed2d0ab6f4df17b4c55b0a657287db8684af9c42ea546b21b1041b3dde"}, + {file = "pytest_cov-6.1.1.tar.gz", hash = "sha256:46935f7aaefba760e716c2ebfbe1c216240b9592966e7da99ea8292d4d3e2a0a"}, ] [package.dependencies] -coverage = {version = ">=5.2.1", extras = ["toml"]} +coverage = {version = ">=7.5", extras = ["toml"]} pytest = ">=4.6" [package.extras] -testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] [[package]] name = "pyyaml" @@ -1325,14 +1379,14 @@ files = [ [[package]] name = "requests" -version = "2.31.0" +version = "2.32.3" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -1347,18 +1401,18 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "respx" -version = "0.20.2" +version = "0.22.0" description = "A utility for mocking out the Python HTTPX and HTTP Core libraries." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "respx-0.20.2-py2.py3-none-any.whl", hash = "sha256:ab8e1cf6da28a5b2dd883ea617f8130f77f676736e6e9e4a25817ad116a172c9"}, - {file = "respx-0.20.2.tar.gz", hash = "sha256:07cf4108b1c88b82010f67d3c831dae33a375c7b436e54d87737c7f9f99be643"}, + {file = "respx-0.22.0-py2.py3-none-any.whl", hash = "sha256:631128d4c9aba15e56903fb5f66fb1eff412ce28dd387ca3a81339e52dbd3ad0"}, + {file = "respx-0.22.0.tar.gz", hash = "sha256:3c8924caa2a50bd71aefc07aa812f2466ff489f1848c96e954a5362d17095d91"}, ] [package.dependencies] -httpx = ">=0.21.0" +httpx = ">=0.25.0" [[package]] name = "restructuredtext-lint" @@ -1374,6 +1428,26 @@ files = [ [package.dependencies] docutils = ">=0.11,<1.0" +[[package]] +name = "rich" +version = "14.0.0" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +optional = false +python-versions = ">=3.8.0" +groups = ["dev"] +files = [ + {file = "rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0"}, + {file = "rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725"}, +] + +[package.dependencies] +markdown-it-py = ">=2.2.0" +pygments = ">=2.13.0,<3.0.0" +typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.11\""} + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<9)"] + [[package]] name = "setuptools" version = "80.4.0" @@ -1395,18 +1469,6 @@ enabler = ["pytest-enabler (>=2.2)"] test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"] -[[package]] -name = "smmap" -version = "5.0.2" -description = "A pure Python implementation of a sliding window memory map manager" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e"}, - {file = "smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5"}, -] - [[package]] name = "sniffio" version = "1.3.1" @@ -1433,22 +1495,22 @@ files = [ [[package]] name = "starlette" -version = "0.27.0" +version = "0.46.2" description = "The little ASGI library that shines." optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"}, - {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"}, + {file = "starlette-0.46.2-py3-none-any.whl", hash = "sha256:595633ce89f8ffa71a015caed34a5b2dc1c0cdb3f0f1fbd1e69339cf2abeec35"}, + {file = "starlette-0.46.2.tar.gz", hash = "sha256:7f7361f34eed179294600af672f565727419830b54b7b084efe44bb82d2fccd5"}, ] [package.dependencies] -anyio = ">=3.4.0,<5" +anyio = ">=3.6.2,<5" typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} [package.extras] -full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"] +full = ["httpx (>=0.27.0,<0.29.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.18)", "pyyaml"] [[package]] name = "stevedore" @@ -1477,18 +1539,6 @@ files = [ {file = "tokenize_rt-6.1.0.tar.gz", hash = "sha256:e8ee836616c0877ab7c7b54776d2fefcc3bde714449a206762425ae114b53c86"}, ] -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -groups = ["dev"] -files = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] - [[package]] name = "tomli" version = "2.2.1" @@ -1544,6 +1594,18 @@ files = [ {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, ] +[[package]] +name = "tzdata" +version = "2025.2" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +groups = ["main"] +files = [ + {file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"}, + {file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"}, +] + [[package]] name = "urllib3" version = "2.4.0" @@ -1564,56 +1626,57 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "uvicorn" -version = "0.16.0" +version = "0.34.2" description = "The lightning-fast ASGI server." optional = false -python-versions = "*" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "uvicorn-0.16.0-py3-none-any.whl", hash = "sha256:d8c839231f270adaa6d338d525e2652a0b4a5f4c2430b5c4ef6ae4d11776b0d2"}, - {file = "uvicorn-0.16.0.tar.gz", hash = "sha256:eacb66afa65e0648fcbce5e746b135d09722231ffffc61883d4fac2b62fbea8d"}, + {file = "uvicorn-0.34.2-py3-none-any.whl", hash = "sha256:deb49af569084536d269fe0a6d67e3754f104cf03aba7c11c40f01aadf33c403"}, + {file = "uvicorn-0.34.2.tar.gz", hash = "sha256:0e929828f6186353a80b58ea719861d2629d766293b6d19baf086ba31d4f3328"}, ] [package.dependencies] -asgiref = ">=3.4.0" click = ">=7.0" h11 = ">=0.8" +typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} [package.extras] -standard = ["PyYAML (>=5.1)", "colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.2.0,<0.4.0)", "python-dotenv (>=0.13)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1) ; sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"", "watchgod (>=0.6)", "websockets (>=10.0) ; python_version >= \"3.7\"", "websockets (>=9.1) ; python_version < \"3.7\""] +standard = ["colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1) ; sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"", "watchfiles (>=0.13)", "websockets (>=10.4)"] [[package]] name = "wemake-python-styleguide" -version = "0.16.0" +version = "0.19.2" description = "The strictest and most opinionated python linter ever" optional = false -python-versions = ">=3.6,<4.0" +python-versions = "<4.0,>=3.9" groups = ["dev"] files = [ - {file = "wemake-python-styleguide-0.16.0.tar.gz", hash = "sha256:3bf0a4962404e6fd6fa479e72e2ba3fb75d5920ea6c44b72b45240c9e519543c"}, - {file = "wemake_python_styleguide-0.16.0-py3-none-any.whl", hash = "sha256:8caa92b4aa77b08a505d718553238812d1b612b1036bc171ca3aa18345efe0b4"}, + {file = "wemake_python_styleguide-0.19.2-py3-none-any.whl", hash = "sha256:d53205dbb629755026d853d15fb3ca03ebb2717c97de4198b5676b9bdc0663bd"}, + {file = "wemake_python_styleguide-0.19.2.tar.gz", hash = "sha256:850fe70e6d525fd37ac51778e552a121a489f1bd057184de96ffd74a09aef414"}, ] [package.dependencies] astor = ">=0.8,<0.9" attrs = "*" darglint = ">=1.2,<2.0" -flake8 = ">=3.7,<5" -flake8-bandit = ">=2.1,<3.0" -flake8-broken-line = ">=0.3,<0.5" -flake8-bugbear = ">=20.1,<22.0" +flake8 = ">=7.0,<8.0" +flake8-bandit = ">=4.1,<5.0" +flake8-broken-line = ">=1.0,<2.0" +flake8-bugbear = ">=24.2,<25.0" flake8-commas = ">=2.0,<3.0" flake8-comprehensions = ">=3.1,<4.0" flake8-debugger = ">=4.0,<5.0" flake8-docstrings = ">=1.3,<2.0" -flake8-eradicate = ">=1.0,<2.0" -flake8-isort = ">=4.0,<5.0" +flake8-eradicate = ">=1.5,<2.0" +flake8-isort = ">=6.0,<7.0" flake8-quotes = ">=3.0,<4.0" -flake8-rst-docstrings = ">=0.2.3,<0.3.0" +flake8-rst-docstrings = ">=0.3,<0.4" flake8-string-format = ">=0.3,<0.4" -pep8-naming = ">=0.11,<0.13" +pep8-naming = ">=0.13,<0.14" pygments = ">=2.4,<3.0" -typing_extensions = ">=3.6,<5.0" +setuptools = "*" +typing_extensions = ">=4.0,<5.0" [[package]] name = "win32-setctime" @@ -1633,5 +1696,5 @@ dev = ["black (>=19.3b0) ; python_version >= \"3.6\"", "pytest (>=4.6.2)"] [metadata] lock-version = "2.1" -python-versions = ">=3.9,<3.13" -content-hash = "fb06209fa4d2c8171876f51348bb90d77cffd1c4508026b208dfec52c278ab4e" +python-versions = ">=3.9,<=3.13" +content-hash = "bda0e2f3b1e038d1b1202f08d50c91f704faa8206a2d035e6789b013ae50534c" diff --git a/pybotx/async_buffer.py b/pybotx/async_buffer.py index d5e8a8a5..ab965560 100644 --- a/pybotx/async_buffer.py +++ b/pybotx/async_buffer.py @@ -1,3 +1,4 @@ +import abc import os from typing import Optional @@ -8,26 +9,30 @@ class AsyncBufferBase(Protocol): - async def seek(self, cursor: int, whence: int = os.SEEK_SET) -> int: - ... # noqa: WPS428 + async def seek( + self, + cursor: int, + whence: int = os.SEEK_SET, + ) -> int: ... - async def tell(self) -> int: - ... # noqa: WPS428 + async def tell(self) -> int: ... class AsyncBufferWritable(AsyncBufferBase): - async def write(self, content: bytes) -> int: - ... # noqa: WPS428 + @abc.abstractmethod + async def write(self, content: bytes) -> int: ... class AsyncBufferReadable(AsyncBufferBase): - async def read(self, bytes_to_read: Optional[int] = None) -> bytes: - ... # noqa: WPS428 + @abc.abstractmethod + async def read( + self, + bytes_to_read: Optional[int] = None, + ) -> bytes: ... async def get_file_size(async_buffer: AsyncBufferReadable) -> int: await async_buffer.seek(0, os.SEEK_END) file_size = await async_buffer.tell() await async_buffer.seek(0) - return file_size diff --git a/pybotx/bot/callbacks/callback_manager.py b/pybotx/bot/callbacks/callback_manager.py index 76568f23..7b17a2b9 100644 --- a/pybotx/bot/callbacks/callback_manager.py +++ b/pybotx/bot/callbacks/callback_manager.py @@ -69,16 +69,14 @@ def setup_callback_timeout_alarm(self, sync_id: UUID, timeout: float) -> None: def cancel_callback_timeout_alarm( self, sync_id: UUID, - ) -> None: - ... # noqa: WPS428 + ) -> None: ... # noqa: WPS428, E704 @overload def cancel_callback_timeout_alarm( self, sync_id: UUID, return_remaining_time: Literal[True], - ) -> float: - ... # noqa: WPS428 + ) -> float: ... # noqa: WPS428, E704 def cancel_callback_timeout_alarm( self, diff --git a/pybotx/bot/callbacks/callback_repo_proto.py b/pybotx/bot/callbacks/callback_repo_proto.py index 3ef262f5..7c34bf11 100644 --- a/pybotx/bot/callbacks/callback_repo_proto.py +++ b/pybotx/bot/callbacks/callback_repo_proto.py @@ -13,27 +13,25 @@ class CallbackRepoProto(Protocol): - async def create_botx_method_callback(self, sync_id: UUID) -> None: - ... # noqa: WPS428 + async def create_botx_method_callback( + self, + sync_id: UUID, + ) -> None: ... # noqa: WPS428, E704 async def set_botx_method_callback_result( self, callback: BotXMethodCallback, - ) -> None: - ... # noqa: WPS428 + ) -> None: ... # noqa: WPS428, E704 async def wait_botx_method_callback( self, sync_id: UUID, timeout: float, - ) -> BotXMethodCallback: - ... # noqa: WPS428 + ) -> BotXMethodCallback: ... # noqa: WPS428, E704 async def pop_botx_method_callback( self, sync_id: UUID, - ) -> "Future[BotXMethodCallback]": - ... # noqa: WPS428 + ) -> "Future[BotXMethodCallback]": ... # noqa: WPS428, E704 - async def stop_callbacks_waiting(self) -> None: - ... # noqa: WPS428 + async def stop_callbacks_waiting(self) -> None: ... # noqa: WPS428, E704 diff --git a/pybotx/bot/handler.py b/pybotx/bot/handler.py index 4addf2f1..a4933e31 100644 --- a/pybotx/bot/handler.py +++ b/pybotx/bot/handler.py @@ -1,6 +1,14 @@ from dataclasses import dataclass from functools import partial -from typing import TYPE_CHECKING, Awaitable, Callable, List, Literal, TypeVar, Union +from typing import ( + TYPE_CHECKING, + Awaitable, + Callable, + List, + Literal, + TypeVar, + Union, +) from pybotx.models.commands import BotCommand from pybotx.models.message.incoming_message import IncomingMessage @@ -69,7 +77,10 @@ async def __call__(self, message: IncomingMessage, bot: "Bot") -> None: handler_func = self.handler_func for middleware in self.middlewares[::-1]: - handler_func = partial(middleware, call_next=handler_func) + handler_func = partial( + middleware, + call_next=handler_func, # type: ignore[call-arg] + ) await handler_func(message, bot) diff --git a/pybotx/bot/handler_collector.py b/pybotx/bot/handler_collector.py index af05836e..3d07d146 100644 --- a/pybotx/bot/handler_collector.py +++ b/pybotx/bot/handler_collector.py @@ -59,6 +59,11 @@ if TYPE_CHECKING: # To avoid circular import from pybotx.bot.bot import Bot +MessageHandlerDecorator = Callable[ + [IncomingMessageHandlerFunc], + IncomingMessageHandlerFunc, +] + class HandlerCollector: VALID_COMMAND_NAME_RE = re.compile(r"^\/[^\s\/]+$", flags=re.UNICODE) @@ -194,16 +199,14 @@ def decorator( def default_message_handler( self, handler_func: IncomingMessageHandlerFunc, - ) -> IncomingMessageHandlerFunc: - ... # noqa: WPS428 + ) -> IncomingMessageHandlerFunc: ... # noqa: WPS428, E704 @overload def default_message_handler( self, *, middlewares: Optional[Sequence[Middleware]] = None, - ) -> Callable[[IncomingMessageHandlerFunc], IncomingMessageHandlerFunc]: - ... # noqa: WPS428 + ) -> MessageHandlerDecorator: ... # noqa: WPS428, E704 def default_message_handler( # noqa: WPS320 self, diff --git a/pybotx/image_validators.py b/pybotx/image_validators.py index 6f8c4f4c..0a72c288 100644 --- a/pybotx/image_validators.py +++ b/pybotx/image_validators.py @@ -1,7 +1,7 @@ from pybotx.async_buffer import AsyncBufferReadable, get_file_size from pybotx.constants import STICKER_IMAGE_MAX_SIZE -PNG_MAGIC_BYTES: bytes = b"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A" +PNG_MAGIC_BYTES: bytes = b"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a" async def ensure_file_content_is_png(async_buffer: AsyncBufferReadable) -> None: diff --git a/pybotx/models/async_files.py b/pybotx/models/async_files.py index 0ecb5f91..f41940e0 100644 --- a/pybotx/models/async_files.py +++ b/pybotx/models/async_files.py @@ -52,7 +52,6 @@ class Image(AsyncFileBase): @dataclass class Video(AsyncFileBase): type: Literal[AttachmentTypes.VIDEO] - duration: int @@ -64,7 +63,6 @@ class Document(AsyncFileBase): @dataclass class Voice(AsyncFileBase): type: Literal[AttachmentTypes.VOICE] - duration: int @@ -78,12 +76,6 @@ class APIAsyncFileBase(VerifiedPayloadBaseModel): file_hash: str class Config: - """BotX sends extra fields which are used by client only. - - We skip their validation, but extra fields will be saved during - serialization/deserialization. - """ - extra = "allow" @@ -93,7 +85,6 @@ class ApiAsyncFileImage(APIAsyncFileBase): class ApiAsyncFileVideo(APIAsyncFileBase): type: Literal[APIAttachmentTypes.VIDEO] - duration: int @@ -103,7 +94,6 @@ class ApiAsyncFileDocument(APIAsyncFileBase): class ApiAsyncFileVoice(APIAsyncFileBase): type: Literal[APIAttachmentTypes.VOICE] - duration: int @@ -121,7 +111,6 @@ def convert_async_file_from_domain(file: File) -> APIAsyncFile: attachment_type = convert_attachment_type_from_domain(file.type) if attachment_type == APIAttachmentTypes.IMAGE: - attachment_type = cast(Literal[APIAttachmentTypes.IMAGE], attachment_type) file = cast(Image, file) return ApiAsyncFileImage( @@ -135,7 +124,6 @@ def convert_async_file_from_domain(file: File) -> APIAsyncFile: ) if attachment_type == APIAttachmentTypes.VIDEO: - attachment_type = cast(Literal[APIAttachmentTypes.VIDEO], attachment_type) file = cast(Video, file) return ApiAsyncFileVideo( @@ -150,7 +138,6 @@ def convert_async_file_from_domain(file: File) -> APIAsyncFile: ) if attachment_type == APIAttachmentTypes.DOCUMENT: - attachment_type = cast(Literal[APIAttachmentTypes.DOCUMENT], attachment_type) file = cast(Document, file) return ApiAsyncFileDocument( @@ -164,7 +151,6 @@ def convert_async_file_from_domain(file: File) -> APIAsyncFile: ) if attachment_type == APIAttachmentTypes.VOICE: - attachment_type = cast(Literal[APIAttachmentTypes.VOICE], attachment_type) file = cast(Voice, file) return ApiAsyncFileVoice( @@ -185,7 +171,6 @@ def convert_async_file_to_domain(async_file: APIAsyncFile) -> File: attachment_type = convert_attachment_type_to_domain(async_file.type) if attachment_type == AttachmentTypes.IMAGE: - attachment_type = cast(Literal[AttachmentTypes.IMAGE], attachment_type) async_file = cast(ApiAsyncFileImage, async_file) return Image( @@ -200,7 +185,6 @@ def convert_async_file_to_domain(async_file: APIAsyncFile) -> File: ) if attachment_type == AttachmentTypes.VIDEO: - attachment_type = cast(Literal[AttachmentTypes.VIDEO], attachment_type) async_file = cast(ApiAsyncFileVideo, async_file) return Video( @@ -216,7 +200,6 @@ def convert_async_file_to_domain(async_file: APIAsyncFile) -> File: ) if attachment_type == AttachmentTypes.DOCUMENT: - attachment_type = cast(Literal[AttachmentTypes.DOCUMENT], attachment_type) async_file = cast(ApiAsyncFileDocument, async_file) return Document( @@ -231,7 +214,6 @@ def convert_async_file_to_domain(async_file: APIAsyncFile) -> File: ) if attachment_type == AttachmentTypes.VOICE: - attachment_type = cast(Literal[AttachmentTypes.VOICE], attachment_type) async_file = cast(ApiAsyncFileVoice, async_file) return Voice( diff --git a/pybotx/models/attachments.py b/pybotx/models/attachments.py index 899fd9ce..628434f2 100644 --- a/pybotx/models/attachments.py +++ b/pybotx/models/attachments.py @@ -220,7 +220,10 @@ def convert_api_attachment_to_domain( # noqa: WPS212 attachment_type = convert_attachment_type_to_domain(api_attachment.type) if attachment_type == AttachmentTypes.IMAGE: - attachment_type = cast(Literal[AttachmentTypes.IMAGE], attachment_type) + attachment_type = cast( # type: ignore[redundant-cast] + Literal[AttachmentTypes.IMAGE], + attachment_type, + ) api_attachment = cast(BotAPIAttachmentImage, api_attachment) content = decode_rfc2397(api_attachment.data.content) @@ -233,7 +236,10 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.VIDEO: - attachment_type = cast(Literal[AttachmentTypes.VIDEO], attachment_type) + attachment_type = cast( # type: ignore[redundant-cast] + Literal[AttachmentTypes.VIDEO], + attachment_type, + ) api_attachment = cast(BotAPIAttachmentVideo, api_attachment) content = decode_rfc2397(api_attachment.data.content) @@ -247,7 +253,10 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.DOCUMENT: - attachment_type = cast(Literal[AttachmentTypes.DOCUMENT], attachment_type) + attachment_type = cast( # type: ignore[redundant-cast] + Literal[AttachmentTypes.DOCUMENT], + attachment_type, + ) api_attachment = cast(BotAPIAttachmentDocument, api_attachment) content = decode_rfc2397(api_attachment.data.content) @@ -260,7 +269,10 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.VOICE: - attachment_type = cast(Literal[AttachmentTypes.VOICE], attachment_type) + attachment_type = cast( # type: ignore[redundant-cast] + Literal[AttachmentTypes.VOICE], + attachment_type, + ) api_attachment = cast(BotAPIAttachmentVoice, api_attachment) content = decode_rfc2397(api_attachment.data.content) attachment_extension = get_attachment_extension_from_encoded_content( @@ -277,7 +289,10 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.LOCATION: - attachment_type = cast(Literal[AttachmentTypes.LOCATION], attachment_type) + attachment_type = cast( # type: ignore[redundant-cast] + Literal[AttachmentTypes.LOCATION], + attachment_type, + ) api_attachment = cast(BotAPIAttachmentLocation, api_attachment) return Location( @@ -288,7 +303,10 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.CONTACT: - attachment_type = cast(Literal[AttachmentTypes.CONTACT], attachment_type) + attachment_type = cast( # type: ignore[redundant-cast] + Literal[AttachmentTypes.CONTACT], + attachment_type, + ) api_attachment = cast(BotAPIAttachmentContact, api_attachment) return Contact( @@ -296,7 +314,6 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.LINK: - attachment_type = cast(Literal[AttachmentTypes.LINK], attachment_type) api_attachment = cast(BotAPIAttachmentLink, api_attachment) return Link( @@ -307,7 +324,6 @@ def convert_api_attachment_to_domain( # noqa: WPS212 ) if attachment_type == AttachmentTypes.STICKER: - attachment_type = cast(Literal[AttachmentTypes.STICKER], attachment_type) api_attachment = cast(BotAPIAttachmentSticker, api_attachment) return Sticker( diff --git a/pybotx/models/chats.py b/pybotx/models/chats.py index c82aaf44..817879cc 100644 --- a/pybotx/models/chats.py +++ b/pybotx/models/chats.py @@ -1,6 +1,5 @@ from dataclasses import dataclass from datetime import datetime -from datetime import datetime as dt from typing import List, Optional from uuid import UUID @@ -72,7 +71,7 @@ class ChatInfo: creator_id: Optional[UUID] description: Optional[str] chat_id: UUID - created_at: dt + created_at: datetime members: List[ChatInfoMember] name: str shared_history: bool diff --git a/pybotx/models/enums.py b/pybotx/models/enums.py index abb124d2..05bc35fa 100644 --- a/pybotx/models/enums.py +++ b/pybotx/models/enums.py @@ -307,13 +307,13 @@ def convert_chat_type_from_domain(chat_type: ChatTypes) -> APIChatTypes: @overload def convert_chat_type_to_domain( chat_type: APIChatTypes, -) -> ChatTypes: - ... # noqa: WPS428 +) -> ChatTypes: ... # noqa: WPS428, E704 @overload -def convert_chat_type_to_domain(chat_type: str) -> UNSUPPORTED: - ... # noqa: WPS428 +def convert_chat_type_to_domain( + chat_type: str, +) -> UNSUPPORTED: ... # noqa: WPS428, E704 def convert_chat_type_to_domain( @@ -340,15 +340,13 @@ def convert_chat_type_to_domain( @overload def convert_sync_source_type_to_domain( sync_type: APISyncSourceTypes, -) -> SyncSourceTypes: - ... # noqa: WPS428 +) -> SyncSourceTypes: ... # noqa: WPS428, E704 @overload def convert_sync_source_type_to_domain( sync_type: str, -) -> UNSUPPORTED: - ... # noqa: WPS428 +) -> UNSUPPORTED: ... # noqa: WPS428, E704 def convert_sync_source_type_to_domain( diff --git a/pybotx/models/message/incoming_message.py b/pybotx/models/message/incoming_message.py index 5d494e17..d11a1488 100644 --- a/pybotx/models/message/incoming_message.py +++ b/pybotx/models/message/incoming_message.py @@ -154,11 +154,9 @@ def _convert_bot_api_mention_to_domain(api_mention_data: BotAPIMentionData) -> M def convert_bot_api_entity_to_domain(api_entity: BotAPIEntity) -> Entity: if api_entity.type == BotAPIEntityTypes.MENTION: - api_entity = cast(BotAPIMention, api_entity) return _convert_bot_api_mention_to_domain(api_entity.data) if api_entity.type == BotAPIEntityTypes.FORWARD: - api_entity = cast(BotAPIForward, api_entity) return Forward( chat_id=api_entity.data.group_chat_id, @@ -170,7 +168,6 @@ def convert_bot_api_entity_to_domain(api_entity: BotAPIEntity) -> Entity: ) if api_entity.type == BotAPIEntityTypes.REPLY: - api_entity = cast(BotAPIReply, api_entity) mentions = MentionList() for api_mention_data in api_entity.data.mentions: diff --git a/pyproject.toml b/pyproject.toml index c56bdd5d..13f6f6b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,40 +13,46 @@ repository = "https://github.com/ExpressApp/pybotx" [tool.poetry.dependencies] -python = ">=3.9,<3.13" +python = ">=3.9,<=3.13" -aiofiles = ">=0.7.0,<24.0.0" -httpx = "^0.25.0" +aiofiles = ">=0.7.0,<=24.1.0" +httpx = "^0.28.0" # The v1.0.3 cause some troubles with no-wait callbacks functionality. # It will be fixed in the next versions. # https://github.com/encode/httpcore/pull/880 httpcore = "1.0.9" loguru = ">=0.6.0,<0.7.0" pydantic = ">=1.6.0,<1.11.0" -aiocsv = ">=1.2.3,<1.3.0" +aiocsv = ">=1.2.3,<=1.4.0" pyjwt = ">=2.0.0,<3.0.0" -mypy-extensions = ">=0.2.0,<0.5.0" +mypy-extensions = ">=0.2.0,<=1.1.0" +factory-boy = ">=3.3.3,<=4.0.0" +deepdiff = "^8.5.0,<=9.0.0" [tool.poetry.group.dev.dependencies] -add-trailing-comma = "2.2.1" -autoflake = "1.7.8" -black = "22.3.0" -isort = "5.10.1" -mypy = "0.910.0" +add-trailing-comma = "3.1.0" +autoflake = "2.3.1" +black = "25.1.0" +isort = "6.0.1" +mypy = "1.15.0" typing-extensions = ">=3.7.4,<5.0.0" -wemake-python-styleguide = "0.16.0" -bandit = "1.7.2" # https://github.com/PyCQA/bandit/issues/837 +wemake-python-styleguide = "0.19.2" +bandit = "1.8.3" # https://github.com/PyCQA/bandit/issues/837 -pytest = "7.2.0" -pytest-asyncio = "0.16.0" -pytest-cov = "4.0.0" -requests = "2.31.0" -respx = "0.20.2" +pytest = "8.3.5" +pytest-asyncio = "0.26.0" +pytest-cov = "6.1.1" +requests = "2.32.3" +respx = "0.22.0" -fastapi = "0.95.2" -starlette = "0.27.0" # TODO: Drop dependency after updating end-to-end test -uvicorn = "0.16.0" +fastapi = "0.115.12 " +starlette = "0.46.2" # TODO: Drop dependency after updating end-to-end test +uvicorn = "0.34.2" [build-system] -requires = ["poetry>=0.12"] +requires = ["poetry>=2.1.3"] build-backend = "poetry.masonry.api" + +[tool.pytest.ini_options] +asyncio_mode = "auto" +asyncio_default_fixture_loop_scope = "function" diff --git a/setup.cfg b/setup.cfg index 6e87b6be..0463678d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -137,6 +137,7 @@ ignore = WPS603, # Forbidden `assert` S101, + E704, [tool:pytest] diff --git a/tests/client/test_botx_method.py b/tests/client/test_botx_method.py index be2a63e2..b81f97a4 100644 --- a/tests/client/test_botx_method.py +++ b/tests/client/test_botx_method.py @@ -168,7 +168,7 @@ async def test__botx_method__invalid_schema_raises_invalid_botx_response_payload await method.execute(payload) # - Assert - - assert '{"invalid": "schema"}' in str(exc.value) + assert '{"invalid":"schema"}' in str(exc.value) assert endpoint.called diff --git a/tests/client/test_botx_method_callback.py b/tests/client/test_botx_method_callback.py index 95781111..3b609646 100644 --- a/tests/client/test_botx_method_callback.py +++ b/tests/client/test_botx_method_callback.py @@ -1,4 +1,4 @@ -# type: ignore [attr-defined] +# mypy: disable-error-code=attr-defined import asyncio import time diff --git a/tests/system_events/factories.py b/tests/system_events/factories.py index bb84df76..264874da 100644 --- a/tests/system_events/factories.py +++ b/tests/system_events/factories.py @@ -1,18 +1,17 @@ import uuid from typing import Any, Dict, List, Optional -from factory.base import DictFactory # type: ignore -from factory.declarations import SubFactory # type: ignore +from factory.base import DictFactory +from factory.declarations import SubFactory -class DeviceMetaFactory(DictFactory): # type: ignore[misc] - +class DeviceMetaFactory(DictFactory): permissions: Optional[str] = None pushes: Optional[str] = None timezone: Optional[str] = None -class FromFactory(DictFactory): # type: ignore[misc] +class FromFactory(DictFactory): user_huid: Optional[str] = None group_chat_id: str = "8dada2c8-67a6-4434-9dec-570d244e78ee" ad_login: Optional[str] = None @@ -22,7 +21,7 @@ class FromFactory(DictFactory): # type: ignore[misc] manufacturer: Optional[str] = None device: Optional[str] = None device_software: Optional[str] = None - device_meta: Dict[str, Any] = SubFactory(DeviceMetaFactory) # noqa: F821 + device_meta: Any = SubFactory(DeviceMetaFactory) # type: ignore[no-untyped-call] platform: Optional[str] = None platform_package_id: Optional[str] = None is_admin: Optional[bool] = None @@ -32,29 +31,24 @@ class FromFactory(DictFactory): # type: ignore[misc] host: str = "cts.ccteam.ru" -class CommandDataFactory(DictFactory): # type: ignore[misc] - +class CommandDataFactory(DictFactory): added_members: List[str] = [uuid.uuid4().hex, uuid.uuid4().hex] -class CommandFactory(DictFactory): # type: ignore[misc] - +class CommandFactory(DictFactory): body: str = "system:user_joined_to_chat" command_type: str = "system" - data: Dict[str, Any] = SubFactory(CommandDataFactory) # noqa: F821 + data: Any = SubFactory(CommandDataFactory) # type: ignore[no-untyped-call] metadata: Dict[str, Any] = {} -class BotAPIJoinToChatFactory(DictFactory): # type: ignore[misc] - +class BotAPIJoinToChatFactory(DictFactory): sync_id: str = uuid.uuid4().hex - command: Dict[str, Any] = SubFactory(CommandFactory) # noqa: F821 + command: Any = SubFactory(CommandFactory) # type: ignore[no-untyped-call] async_files: List[str] = [] attachments: List[str] = [] entities: List[str] = [] - from_: Dict[str, Any] = SubFactory( - FromFactory, - ) # noqa: F821 + from_: Any = SubFactory(FromFactory) # type: ignore[no-untyped-call] bot_id: str = uuid.uuid4().hex proto_version: int = 4 source_sync_id: Optional[str] = None @@ -63,8 +57,7 @@ class Meta: rename = {"from_": "from"} -class ConferenceChangedDataFactory(DictFactory): # type: ignore[misc] - +class ConferenceChangedDataFactory(DictFactory): access_code = None actor = None added_users = ["5c053f2a-0bdf-4ab1-9bc9-256fee9db7ba"] diff --git a/tests/system_events/test_conference_changed.py b/tests/system_events/test_conference_changed.py index 3dc6ad5c..66eea67e 100644 --- a/tests/system_events/test_conference_changed.py +++ b/tests/system_events/test_conference_changed.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import Any, Callable, Dict, Optional +from typing import Any, Callable, Dict, Optional, cast from uuid import UUID import pytest @@ -14,7 +14,7 @@ ) from pybotx.models.enums import ConferenceLinkTypes from pybotx.models.system_events.conference_changed import ConferenceChangedEvent -from tests.system_events.factories import ConferenceChangedDataFactory # type: ignore +from tests.system_events.factories import ConferenceChangedDataFactory pytestmark = [ pytest.mark.asyncio, @@ -32,9 +32,12 @@ async def test__conference_changed_succeed( api_incoming_message_factory: Callable[..., Dict[str, Any]], ) -> None: # - Arrange - - conference_change_data = ConferenceChangedDataFactory( - call_id=str(call_id), - link_type="public", + conference_change_data = cast( + Dict[str, Any], + ConferenceChangedDataFactory( + call_id=str(call_id), + link_type="public", + ), # type: ignore[no-untyped-call] ) payload = api_incoming_message_factory( body="system:conference_changed", diff --git a/tests/system_events/test_join_to_chat.py b/tests/system_events/test_join_to_chat.py index 6b66fbd4..16622787 100644 --- a/tests/system_events/test_join_to_chat.py +++ b/tests/system_events/test_join_to_chat.py @@ -1,4 +1,4 @@ -from typing import Any, Optional +from typing import Any, Dict, Optional, cast from uuid import UUID import pytest @@ -13,7 +13,7 @@ lifespan_wrapper, ) from pybotx.models.system_events.user_joined_to_chat import JoinToChatEvent -from tests.system_events.factories import BotAPIJoinToChatFactory # type: ignore +from tests.system_events.factories import BotAPIJoinToChatFactory pytestmark = [ pytest.mark.asyncio, @@ -33,7 +33,10 @@ async def test__join_to_chat__succeed( 3. The registered user_joined_to_chat handler is called with this event """ - payload: dict[str, Any] = BotAPIJoinToChatFactory(bot_id=bot_account.id.hex) + payload: Dict[str, Any] = cast( + Dict[str, Any], + BotAPIJoinToChatFactory(bot_id=bot_account.id.hex), # type: ignore[no-untyped-call] + ) collector = HandlerCollector() join_to_chat: Optional[JoinToChatEvent] = None diff --git a/tests/test_base_command.py b/tests/test_base_command.py index a361a76d..7e2937e1 100644 --- a/tests/test_base_command.py +++ b/tests/test_base_command.py @@ -21,7 +21,9 @@ ] -async def test__async_execute_raw_bot_command__invalid_payload_value_error_raised() -> None: +async def test__async_execute_raw_bot_command__invalid_payload_value_error_raised() -> ( + None +): # - Arrange - payload = {"invalid": "command"} built_bot = Bot(collectors=[HandlerCollector()], bot_accounts=[]) @@ -35,7 +37,9 @@ async def test__async_execute_raw_bot_command__invalid_payload_value_error_raise assert "validation" in str(exc.value) -async def test__async_execute_raw_bot_command__unsupported_bot_api_version_error_raised() -> None: +async def test__async_execute_raw_bot_command__unsupported_bot_api_version_error_raised() -> ( + None +): # - Arrange - payload = {"proto_version": "3"} built_bot = Bot(collectors=[HandlerCollector()], bot_accounts=[]) diff --git a/tests/test_handler_collector.py b/tests/test_handler_collector.py index 5d86cf73..727227f0 100644 --- a/tests/test_handler_collector.py +++ b/tests/test_handler_collector.py @@ -146,7 +146,9 @@ async def handler_2(message: IncomingMessage, bot: Bot) -> None: assert "/command" in str(exc.value) -def test__handler_collector__merge_collectors_with_default_handlers_error_raised() -> None: +def test__handler_collector__merge_collectors_with_default_handlers_error_raised() -> ( + None +): # - Arrange - collector = HandlerCollector() @@ -169,7 +171,9 @@ async def handler_2(message: IncomingMessage, bot: Bot) -> None: assert "Default" in str(exc.value) -def test__handler_collector__merge_collectors_with_same_system_events_handlers_error_raised() -> None: +def test__handler_collector__merge_collectors_with_same_system_events_handlers_error_raised() -> ( + None +): # - Arrange - collector = HandlerCollector() @@ -556,7 +560,8 @@ async def test__handler_collector__sync_smartapp_event__decorator__handler_alrea with pytest.raises(ValueError) as exc: @collector.sync_smartapp_event - async def duplicated_handle_sync_smartapp_event(*_: Any) -> Any: - ... + async def duplicated_handle_sync_smartapp_event( + *_: Any, + ) -> Any: ... # noqa: E704 assert str(exc.value) == "Handler for sync smartapp event already registered" diff --git a/tests/test_middlewares.py b/tests/test_middlewares.py index 62dddca1..f573051b 100644 --- a/tests/test_middlewares.py +++ b/tests/test_middlewares.py @@ -35,8 +35,7 @@ async def middleware( bot: Bot, call_next: IncomingMessageHandlerFunc, ) -> None: - nonlocal middlewares_called_order - middlewares_called_order.append(number) + middlewares_called_order.append(number) # noqa: F824 await call_next(message, bot) @@ -84,8 +83,7 @@ async def middleware( bot: Bot, call_next: IncomingMessageHandlerFunc, ) -> None: - nonlocal middlewares_called_order - middlewares_called_order.append(number) + middlewares_called_order.append(number) # noqa: F824 await call_next(message, bot) @@ -129,8 +127,7 @@ async def middleware( bot: Bot, call_next: IncomingMessageHandlerFunc, ) -> None: - nonlocal middlewares_called_order - middlewares_called_order.append(number) + middlewares_called_order.append(number) # noqa: F824 await call_next(message, bot) @@ -177,7 +174,7 @@ async def middleware( bot: Bot, call_next: IncomingMessageHandlerFunc, ) -> None: - nonlocal middlewares_called_order + nonlocal middlewares_called_order # noqa: F824 middlewares_called_order.append(number) await call_next(message, bot) From dc9141dbe224e6dbb20d718fefff9e72a8884a24 Mon Sep 17 00:00:00 2001 From: Aleksandr Osovskii Date: Thu, 15 May 2025 11:27:04 +0300 Subject: [PATCH 14/18] fix dev req --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 13f6f6b5..241bf3ff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,8 +26,6 @@ pydantic = ">=1.6.0,<1.11.0" aiocsv = ">=1.2.3,<=1.4.0" pyjwt = ">=2.0.0,<3.0.0" mypy-extensions = ">=0.2.0,<=1.1.0" -factory-boy = ">=3.3.3,<=4.0.0" -deepdiff = "^8.5.0,<=9.0.0" [tool.poetry.group.dev.dependencies] add-trailing-comma = "3.1.0" @@ -44,6 +42,8 @@ pytest-asyncio = "0.26.0" pytest-cov = "6.1.1" requests = "2.32.3" respx = "0.22.0" +factory-boy = ">=3.3.3,<=4.0.0" +deepdiff = "^8.5.0,<=9.0.0" fastapi = "0.115.12 " starlette = "0.46.2" # TODO: Drop dependency after updating end-to-end test From 0669d78f37367cd125ed96fa69d8d943412e9276 Mon Sep 17 00:00:00 2001 From: Aleksandr Osovskii Date: Thu, 15 May 2025 20:15:27 +0300 Subject: [PATCH 15/18] hofix: publish lib --- .github/workflows/publish-pypi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index da5dd6d1..0d83c244 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -11,6 +11,6 @@ jobs: - name: Assert tag is from master run: git branch -a --contains $(git describe --tags) | grep master - name: Build and publish to pypi - uses: JRubics/poetry-publish@v1.8 + uses: JRubics/poetry-publish@v2.1 with: pypi_token: ${{ secrets.PYPI_TOKEN }} From e8c766e3d623b46880ad0788e9638cdf299396b7 Mon Sep 17 00:00:00 2001 From: Aleksandr Osovskii Date: Thu, 15 May 2025 20:18:24 +0300 Subject: [PATCH 16/18] hofix: publish lib --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 241bf3ff..414e82be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pybotx" -version = "0.75.0" +version = "0.75.1" description = "A python library for interacting with eXpress BotX API" authors = [ "Sidnev Nikolay ", From edf4fc83a1992bd076eecf63cacc52ed1e518897 Mon Sep 17 00:00:00 2001 From: Aleksandr Osovskii Date: Thu, 15 May 2025 20:19:06 +0300 Subject: [PATCH 17/18] hofix: publish lib --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 414e82be..241bf3ff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pybotx" -version = "0.75.1" +version = "0.75.0" description = "A python library for interacting with eXpress BotX API" authors = [ "Sidnev Nikolay ", From e99f944188e08f15d20feb32760e8aa2d5eebb88 Mon Sep 17 00:00:00 2001 From: Aleksandr Osovskii Date: Thu, 15 May 2025 20:22:50 +0300 Subject: [PATCH 18/18] hofix: publish lib --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 241bf3ff..5bbe5ff6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ repository = "https://github.com/ExpressApp/pybotx" [tool.poetry.dependencies] -python = ">=3.9,<=3.13" +python = ">=3.9,<3.14" aiofiles = ">=0.7.0,<=24.1.0" httpx = "^0.28.0"