From 7760ab1d0d7fdd367824a33eed50ad7f3bf1671a Mon Sep 17 00:00:00 2001 From: Oleg A Date: Fri, 14 Jun 2024 20:11:08 +0300 Subject: [PATCH] Bump dev dependencies (#1512) * Bump dev dependencies * Pre-commit py3.8 support * Pre-commit py3.8 support (v3.5+) * Mute mypy python version bug --- .github/workflows/tests.yml | 2 +- .pre-commit-config.yaml | 9 ++-- Makefile | 7 ++- aiogram/client/session/middlewares/manager.py | 5 +- aiogram/dispatcher/middlewares/manager.py | 2 +- .../dispatcher/middlewares/user_context.py | 40 +++++++++------ aiogram/filters/command.py | 5 +- ...t_command_scope_all_chat_administrators.py | 4 +- .../bot_command_scope_chat_administrators.py | 4 +- ...passport_element_error_translation_file.py | 4 +- ...assport_element_error_translation_files.py | 4 +- aiogram/utils/keyboard.py | 3 +- aiogram/utils/media_group.py | 8 +-- aiogram/utils/payload.py | 1 + examples/context_addition_from_filter.py | 2 +- examples/echo_bot_webhook.py | 1 + examples/echo_bot_webhook_ssl.py | 1 + examples/own_filter.py | 3 +- pyproject.toml | 50 ++++++++++--------- tests/test_dispatcher/test_dispatcher.py | 12 ++--- 20 files changed, 92 insertions(+), 75 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 90afe538..0d95be48 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -67,7 +67,7 @@ jobs: - name: Lint code run: | - ruff --output-format=github aiogram examples + ruff check --output-format=github aiogram examples mypy aiogram black --check --diff aiogram tests diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bf00554d..c42ea91e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.2.0 + rev: v4.6.0 hooks: - id: "trailing-whitespace" - id: "check-case-conflict" @@ -14,13 +14,12 @@ repos: - id: "check-json" - repo: https://github.com/psf/black - rev: 22.10.0 + rev: 24.4.2 hooks: - id: black files: &files '^(aiogram|tests|examples)' - - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: 'v0.0.215' + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: 'v0.4.9' hooks: - id: ruff - args: [ "--force-exclude" ] diff --git a/Makefile b/Makefile index 324d95c7..41eaba49 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,11 @@ clean: rm -f .coverage rm -rf {build,dist,site,.cache,.mypy_cache,.ruff_cache,reports} +.PHONY: install +install: clean + pip install -e ."[dev,test,docs]" -U --upgrade-strategy=eager + pre-commit install + # ================================================================================================= # Code quality # ================================================================================================= @@ -34,7 +39,7 @@ clean: lint: isort --check-only $(code_dir) black --check --diff $(code_dir) - ruff $(package_dir) + ruff check $(package_dir) $(examples_dir) mypy $(package_dir) .PHONY: reformat diff --git a/aiogram/client/session/middlewares/manager.py b/aiogram/client/session/middlewares/manager.py index 78015309..2346715f 100644 --- a/aiogram/client/session/middlewares/manager.py +++ b/aiogram/client/session/middlewares/manager.py @@ -27,7 +27,10 @@ class RequestMiddlewareManager(Sequence[RequestMiddlewareType]): def __call__( self, middleware: Optional[RequestMiddlewareType] = None, - ) -> Union[Callable[[RequestMiddlewareType], RequestMiddlewareType], RequestMiddlewareType,]: + ) -> Union[ + Callable[[RequestMiddlewareType], RequestMiddlewareType], + RequestMiddlewareType, + ]: if middleware is None: return self.register return self.register(middleware) diff --git a/aiogram/dispatcher/middlewares/manager.py b/aiogram/dispatcher/middlewares/manager.py index a63e1ef4..bcad4dee 100644 --- a/aiogram/dispatcher/middlewares/manager.py +++ b/aiogram/dispatcher/middlewares/manager.py @@ -61,5 +61,5 @@ class MiddlewareManager(Sequence[MiddlewareType[TelegramObject]]): middleware = handler_wrapper for m in reversed(middlewares): - middleware = functools.partial(m, middleware) + middleware = functools.partial(m, middleware) # type: ignore[assignment] return middleware diff --git a/aiogram/dispatcher/middlewares/user_context.py b/aiogram/dispatcher/middlewares/user_context.py index 0c780048..c257079f 100644 --- a/aiogram/dispatcher/middlewares/user_context.py +++ b/aiogram/dispatcher/middlewares/user_context.py @@ -57,17 +57,19 @@ class UserContextMiddleware(BaseMiddleware): return EventContext( chat=event.message.chat, user=event.message.from_user, - thread_id=event.message.message_thread_id - if event.message.is_topic_message - else None, + thread_id=( + event.message.message_thread_id if event.message.is_topic_message else None + ), ) if event.edited_message: return EventContext( chat=event.edited_message.chat, user=event.edited_message.from_user, - thread_id=event.edited_message.message_thread_id - if event.edited_message.is_topic_message - else None, + thread_id=( + event.edited_message.message_thread_id + if event.edited_message.is_topic_message + else None + ), ) if event.channel_post: return EventContext(chat=event.channel_post.chat) @@ -82,10 +84,12 @@ class UserContextMiddleware(BaseMiddleware): return EventContext( chat=event.callback_query.message.chat, user=event.callback_query.from_user, - thread_id=event.callback_query.message.message_thread_id - if not isinstance(event.callback_query.message, InaccessibleMessage) - and event.callback_query.message.is_topic_message - else None, + thread_id=( + event.callback_query.message.message_thread_id + if not isinstance(event.callback_query.message, InaccessibleMessage) + and event.callback_query.message.is_topic_message + else None + ), ) return EventContext(user=event.callback_query.from_user) if event.shipping_query: @@ -132,18 +136,22 @@ class UserContextMiddleware(BaseMiddleware): return EventContext( chat=event.business_message.chat, user=event.business_message.from_user, - thread_id=event.business_message.message_thread_id - if event.business_message.is_topic_message - else None, + thread_id=( + event.business_message.message_thread_id + if event.business_message.is_topic_message + else None + ), business_connection_id=event.business_message.business_connection_id, ) if event.edited_business_message: return EventContext( chat=event.edited_business_message.chat, user=event.edited_business_message.from_user, - thread_id=event.edited_business_message.message_thread_id - if event.edited_business_message.is_topic_message - else None, + thread_id=( + event.edited_business_message.message_thread_id + if event.edited_business_message.is_topic_message + else None + ), business_connection_id=event.edited_business_message.business_connection_id, ) return EventContext() diff --git a/aiogram/filters/command.py b/aiogram/filters/command.py index 6e654531..b4cc5541 100644 --- a/aiogram/filters/command.py +++ b/aiogram/filters/command.py @@ -3,7 +3,6 @@ from __future__ import annotations import re from dataclasses import dataclass, field, replace from typing import ( - TYPE_CHECKING, Any, Dict, Iterable, @@ -11,6 +10,7 @@ from typing import ( Optional, Pattern, Sequence, + TYPE_CHECKING, Union, cast, ) @@ -24,7 +24,8 @@ from aiogram.utils.deep_linking import decode_payload if TYPE_CHECKING: from aiogram import Bot -CommandPatternType = Union[str, re.Pattern, BotCommand] +# TODO: rm type ignore after py3.8 support expiration or mypy bug fix +CommandPatternType = Union[str, re.Pattern, BotCommand] # type: ignore[type-arg] class CommandException(Exception): diff --git a/aiogram/types/bot_command_scope_all_chat_administrators.py b/aiogram/types/bot_command_scope_all_chat_administrators.py index 061945f7..44173636 100644 --- a/aiogram/types/bot_command_scope_all_chat_administrators.py +++ b/aiogram/types/bot_command_scope_all_chat_administrators.py @@ -13,9 +13,9 @@ class BotCommandScopeAllChatAdministrators(BotCommandScope): Source: https://core.telegram.org/bots/api#botcommandscopeallchatadministrators """ - type: Literal[ + type: Literal[BotCommandScopeType.ALL_CHAT_ADMINISTRATORS] = ( BotCommandScopeType.ALL_CHAT_ADMINISTRATORS - ] = BotCommandScopeType.ALL_CHAT_ADMINISTRATORS + ) """Scope type, must be *all_chat_administrators*""" if TYPE_CHECKING: diff --git a/aiogram/types/bot_command_scope_chat_administrators.py b/aiogram/types/bot_command_scope_chat_administrators.py index 8757e98c..f90623ef 100644 --- a/aiogram/types/bot_command_scope_chat_administrators.py +++ b/aiogram/types/bot_command_scope_chat_administrators.py @@ -13,9 +13,9 @@ class BotCommandScopeChatAdministrators(BotCommandScope): Source: https://core.telegram.org/bots/api#botcommandscopechatadministrators """ - type: Literal[ + type: Literal[BotCommandScopeType.CHAT_ADMINISTRATORS] = ( BotCommandScopeType.CHAT_ADMINISTRATORS - ] = BotCommandScopeType.CHAT_ADMINISTRATORS + ) """Scope type, must be *chat_administrators*""" chat_id: Union[int, str] """Unique identifier for the target chat or username of the target supergroup (in the format :code:`@supergroupusername`)""" diff --git a/aiogram/types/passport_element_error_translation_file.py b/aiogram/types/passport_element_error_translation_file.py index a8a207c4..29689ca8 100644 --- a/aiogram/types/passport_element_error_translation_file.py +++ b/aiogram/types/passport_element_error_translation_file.py @@ -13,9 +13,9 @@ class PassportElementErrorTranslationFile(PassportElementError): Source: https://core.telegram.org/bots/api#passportelementerrortranslationfile """ - source: Literal[ + source: Literal[PassportElementErrorType.TRANSLATION_FILE] = ( PassportElementErrorType.TRANSLATION_FILE - ] = PassportElementErrorType.TRANSLATION_FILE + ) """Error source, must be *translation_file*""" type: str """Type of element of the user's Telegram Passport which has the issue, one of 'passport', 'driver_license', 'identity_card', 'internal_passport', 'utility_bill', 'bank_statement', 'rental_agreement', 'passport_registration', 'temporary_registration'""" diff --git a/aiogram/types/passport_element_error_translation_files.py b/aiogram/types/passport_element_error_translation_files.py index 0d8ff504..65e9940e 100644 --- a/aiogram/types/passport_element_error_translation_files.py +++ b/aiogram/types/passport_element_error_translation_files.py @@ -13,9 +13,9 @@ class PassportElementErrorTranslationFiles(PassportElementError): Source: https://core.telegram.org/bots/api#passportelementerrortranslationfiles """ - source: Literal[ + source: Literal[PassportElementErrorType.TRANSLATION_FILES] = ( PassportElementErrorType.TRANSLATION_FILES - ] = PassportElementErrorType.TRANSLATION_FILES + ) """Error source, must be *translation_files*""" type: str """Type of element of the user's Telegram Passport which has the issue, one of 'passport', 'driver_license', 'identity_card', 'internal_passport', 'utility_bill', 'bank_statement', 'rental_agreement', 'passport_registration', 'temporary_registration'""" diff --git a/aiogram/utils/keyboard.py b/aiogram/utils/keyboard.py index ef9b2f52..921c28c1 100644 --- a/aiogram/utils/keyboard.py +++ b/aiogram/utils/keyboard.py @@ -397,8 +397,7 @@ class ReplyKeyboardBuilder(KeyboardBuilder[KeyboardButton]): if TYPE_CHECKING: - def as_markup(self, **kwargs: Any) -> ReplyKeyboardMarkup: - ... + def as_markup(self, **kwargs: Any) -> ReplyKeyboardMarkup: ... def __init__(self, markup: Optional[List[List[KeyboardButton]]] = None) -> None: super().__init__(button_type=KeyboardButton, markup=markup) diff --git a/aiogram/utils/media_group.py b/aiogram/utils/media_group.py index e4277d2f..ff985258 100644 --- a/aiogram/utils/media_group.py +++ b/aiogram/utils/media_group.py @@ -359,8 +359,10 @@ class MediaGroupBuilder: update_first_media["parse_mode"] = None return [ - media.model_copy(update=update_first_media) - if index == 0 and self.caption is not None - else media + ( + media.model_copy(update=update_first_media) + if index == 0 and self.caption is not None + else media + ) for index, media in enumerate(self._media) ] diff --git a/aiogram/utils/payload.py b/aiogram/utils/payload.py index f070dd4e..dbdba653 100644 --- a/aiogram/utils/payload.py +++ b/aiogram/utils/payload.py @@ -60,6 +60,7 @@ Encoding and decoding with your own methods: # result: decoded == "foo" """ + from base64 import urlsafe_b64decode, urlsafe_b64encode from typing import Callable, Optional diff --git a/examples/context_addition_from_filter.py b/examples/context_addition_from_filter.py index 40338940..73143417 100644 --- a/examples/context_addition_from_filter.py +++ b/examples/context_addition_from_filter.py @@ -14,7 +14,7 @@ class HelloFilter(Filter): async def __call__( self, message: Message, - event_from_user: User + event_from_user: User, # Filters also can accept keyword parameters like in handlers ) -> Union[bool, Dict[str, Any]]: if message.text.casefold() == "hello": diff --git a/examples/echo_bot_webhook.py b/examples/echo_bot_webhook.py index 056c3f71..07a83351 100644 --- a/examples/echo_bot_webhook.py +++ b/examples/echo_bot_webhook.py @@ -1,6 +1,7 @@ """ This example shows how to use webhook on behind of any reverse proxy (nginx, traefik, ingress etc.) """ + import logging import sys from os import getenv diff --git a/examples/echo_bot_webhook_ssl.py b/examples/echo_bot_webhook_ssl.py index 45c75015..28c14d1c 100644 --- a/examples/echo_bot_webhook_ssl.py +++ b/examples/echo_bot_webhook_ssl.py @@ -1,6 +1,7 @@ """ This example shows how to use webhook with SSL certificate. """ + import logging import ssl import sys diff --git a/examples/own_filter.py b/examples/own_filter.py index 89101920..af87408a 100644 --- a/examples/own_filter.py +++ b/examples/own_filter.py @@ -14,5 +14,4 @@ class MyFilter(Filter): @router.message(MyFilter("hello")) -async def my_handler(message: Message): - ... +async def my_handler(message: Message): ... diff --git a/pyproject.toml b/pyproject.toml index 131f5d35..5dbd962b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -101,13 +101,13 @@ docs = [ "sphinxcontrib-towncrier~=0.3.2a0", ] dev = [ - "black~=23.10.0", - "isort~=5.12.0", - "ruff~=0.1.1", - "mypy~=1.6.1", + "black~=24.4.2", + "isort~=5.13.2", + "ruff~=0.4.9", + "mypy~=1.10.0", "toml~=0.10.2", - "pre-commit~=3.5.0", - "packaging~=23.1", + "pre-commit~=3.5", + "packaging~=24.1", "motor-types~=1.0.0b4", ] @@ -132,10 +132,10 @@ post-install-commands = [ [tool.hatch.envs.default.scripts] reformat = [ - "black aiogram tests", - "isort aiogram tests", + "black aiogram tests examples", + "isort aiogram tests examples", ] -lint = "ruff aiogram" +lint = "ruff check aiogram tests examples" [tool.hatch.envs.docs] features = [ @@ -202,19 +202,6 @@ python = ["38", "39", "310", "311", "312"] [tool.ruff] line-length = 99 -select = [ - # "C", # TODO: mccabe - code complecity - "C4", - "E", - "F", - "T10", - "T20", - "Q", - "RET", -] -ignore = [ - "F401" -] src = ["aiogram", "tests"] exclude = [ ".git", @@ -230,7 +217,22 @@ exclude = [ ] target-version = "py310" -[tool.ruff.isort] +[tool.ruff.lint] +select = [ + # "C", # TODO: mccabe - code complecity + "C4", + "E", + "F", + "T10", + "T20", + "Q", + "RET", +] +ignore = [ + "F401" +] + +[tool.ruff.lint.isort] known-first-party = [ "aiogram", "finite_state_machine", @@ -238,7 +240,7 @@ known-first-party = [ "routes", ] -[tool.ruff.per-file-ignores] +[tool.ruff.lint.per-file-ignores] "aiogram/client/bot.py" = ["E501"] "aiogram/types/*" = ["E501"] "aiogram/methods/*" = ["E501"] diff --git a/tests/test_dispatcher/test_dispatcher.py b/tests/test_dispatcher/test_dispatcher.py index 56a44e6f..98467934 100644 --- a/tests/test_dispatcher/test_dispatcher.py +++ b/tests/test_dispatcher/test_dispatcher.py @@ -992,17 +992,13 @@ class TestDispatcher: pytest.fail("Expected 'Detected slow response into webhook' warning.") def test_specify_updates_calculation(self): - def simple_msg_handler() -> None: - ... + def simple_msg_handler() -> None: ... - def simple_callback_query_handler() -> None: - ... + def simple_callback_query_handler() -> None: ... - def simple_poll_handler() -> None: - ... + def simple_poll_handler() -> None: ... - def simple_edited_msg_handler() -> None: - ... + def simple_edited_msg_handler() -> None: ... dispatcher = Dispatcher() dispatcher.message.register(simple_msg_handler)