Bump dev dependencies (#1512)

* Bump dev dependencies

* Pre-commit py3.8 support

* Pre-commit py3.8 support (v3.5+)

* Mute mypy python version bug
This commit is contained in:
Oleg A 2024-06-14 20:11:08 +03:00 committed by GitHub
parent 0df95a0276
commit 7760ab1d0d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 92 additions and 75 deletions

View file

@ -67,7 +67,7 @@ jobs:
- name: Lint code - name: Lint code
run: | run: |
ruff --output-format=github aiogram examples ruff check --output-format=github aiogram examples
mypy aiogram mypy aiogram
black --check --diff aiogram tests black --check --diff aiogram tests

View file

@ -1,6 +1,6 @@
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.2.0 rev: v4.6.0
hooks: hooks:
- id: "trailing-whitespace" - id: "trailing-whitespace"
- id: "check-case-conflict" - id: "check-case-conflict"
@ -14,13 +14,12 @@ repos:
- id: "check-json" - id: "check-json"
- repo: https://github.com/psf/black - repo: https://github.com/psf/black
rev: 22.10.0 rev: 24.4.2
hooks: hooks:
- id: black - id: black
files: &files '^(aiogram|tests|examples)' files: &files '^(aiogram|tests|examples)'
- repo: https://github.com/charliermarsh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: 'v0.0.215' rev: 'v0.4.9'
hooks: hooks:
- id: ruff - id: ruff
args: [ "--force-exclude" ]

View file

@ -26,6 +26,11 @@ clean:
rm -f .coverage rm -f .coverage
rm -rf {build,dist,site,.cache,.mypy_cache,.ruff_cache,reports} 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 # Code quality
# ================================================================================================= # =================================================================================================
@ -34,7 +39,7 @@ clean:
lint: lint:
isort --check-only $(code_dir) isort --check-only $(code_dir)
black --check --diff $(code_dir) black --check --diff $(code_dir)
ruff $(package_dir) ruff check $(package_dir) $(examples_dir)
mypy $(package_dir) mypy $(package_dir)
.PHONY: reformat .PHONY: reformat

View file

@ -27,7 +27,10 @@ class RequestMiddlewareManager(Sequence[RequestMiddlewareType]):
def __call__( def __call__(
self, self,
middleware: Optional[RequestMiddlewareType] = None, middleware: Optional[RequestMiddlewareType] = None,
) -> Union[Callable[[RequestMiddlewareType], RequestMiddlewareType], RequestMiddlewareType,]: ) -> Union[
Callable[[RequestMiddlewareType], RequestMiddlewareType],
RequestMiddlewareType,
]:
if middleware is None: if middleware is None:
return self.register return self.register
return self.register(middleware) return self.register(middleware)

View file

@ -61,5 +61,5 @@ class MiddlewareManager(Sequence[MiddlewareType[TelegramObject]]):
middleware = handler_wrapper middleware = handler_wrapper
for m in reversed(middlewares): for m in reversed(middlewares):
middleware = functools.partial(m, middleware) middleware = functools.partial(m, middleware) # type: ignore[assignment]
return middleware return middleware

View file

@ -57,17 +57,19 @@ class UserContextMiddleware(BaseMiddleware):
return EventContext( return EventContext(
chat=event.message.chat, chat=event.message.chat,
user=event.message.from_user, user=event.message.from_user,
thread_id=event.message.message_thread_id thread_id=(
if event.message.is_topic_message event.message.message_thread_id if event.message.is_topic_message else None
else None, ),
) )
if event.edited_message: if event.edited_message:
return EventContext( return EventContext(
chat=event.edited_message.chat, chat=event.edited_message.chat,
user=event.edited_message.from_user, user=event.edited_message.from_user,
thread_id=event.edited_message.message_thread_id thread_id=(
event.edited_message.message_thread_id
if event.edited_message.is_topic_message if event.edited_message.is_topic_message
else None, else None
),
) )
if event.channel_post: if event.channel_post:
return EventContext(chat=event.channel_post.chat) return EventContext(chat=event.channel_post.chat)
@ -82,10 +84,12 @@ class UserContextMiddleware(BaseMiddleware):
return EventContext( return EventContext(
chat=event.callback_query.message.chat, chat=event.callback_query.message.chat,
user=event.callback_query.from_user, user=event.callback_query.from_user,
thread_id=event.callback_query.message.message_thread_id thread_id=(
event.callback_query.message.message_thread_id
if not isinstance(event.callback_query.message, InaccessibleMessage) if not isinstance(event.callback_query.message, InaccessibleMessage)
and event.callback_query.message.is_topic_message and event.callback_query.message.is_topic_message
else None, else None
),
) )
return EventContext(user=event.callback_query.from_user) return EventContext(user=event.callback_query.from_user)
if event.shipping_query: if event.shipping_query:
@ -132,18 +136,22 @@ class UserContextMiddleware(BaseMiddleware):
return EventContext( return EventContext(
chat=event.business_message.chat, chat=event.business_message.chat,
user=event.business_message.from_user, user=event.business_message.from_user,
thread_id=event.business_message.message_thread_id thread_id=(
event.business_message.message_thread_id
if event.business_message.is_topic_message if event.business_message.is_topic_message
else None, else None
),
business_connection_id=event.business_message.business_connection_id, business_connection_id=event.business_message.business_connection_id,
) )
if event.edited_business_message: if event.edited_business_message:
return EventContext( return EventContext(
chat=event.edited_business_message.chat, chat=event.edited_business_message.chat,
user=event.edited_business_message.from_user, user=event.edited_business_message.from_user,
thread_id=event.edited_business_message.message_thread_id thread_id=(
event.edited_business_message.message_thread_id
if event.edited_business_message.is_topic_message if event.edited_business_message.is_topic_message
else None, else None
),
business_connection_id=event.edited_business_message.business_connection_id, business_connection_id=event.edited_business_message.business_connection_id,
) )
return EventContext() return EventContext()

View file

@ -3,7 +3,6 @@ from __future__ import annotations
import re import re
from dataclasses import dataclass, field, replace from dataclasses import dataclass, field, replace
from typing import ( from typing import (
TYPE_CHECKING,
Any, Any,
Dict, Dict,
Iterable, Iterable,
@ -11,6 +10,7 @@ from typing import (
Optional, Optional,
Pattern, Pattern,
Sequence, Sequence,
TYPE_CHECKING,
Union, Union,
cast, cast,
) )
@ -24,7 +24,8 @@ from aiogram.utils.deep_linking import decode_payload
if TYPE_CHECKING: if TYPE_CHECKING:
from aiogram import Bot 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): class CommandException(Exception):

View file

@ -13,9 +13,9 @@ class BotCommandScopeAllChatAdministrators(BotCommandScope):
Source: https://core.telegram.org/bots/api#botcommandscopeallchatadministrators Source: https://core.telegram.org/bots/api#botcommandscopeallchatadministrators
""" """
type: Literal[ type: Literal[BotCommandScopeType.ALL_CHAT_ADMINISTRATORS] = (
BotCommandScopeType.ALL_CHAT_ADMINISTRATORS BotCommandScopeType.ALL_CHAT_ADMINISTRATORS
] = BotCommandScopeType.ALL_CHAT_ADMINISTRATORS )
"""Scope type, must be *all_chat_administrators*""" """Scope type, must be *all_chat_administrators*"""
if TYPE_CHECKING: if TYPE_CHECKING:

View file

@ -13,9 +13,9 @@ class BotCommandScopeChatAdministrators(BotCommandScope):
Source: https://core.telegram.org/bots/api#botcommandscopechatadministrators Source: https://core.telegram.org/bots/api#botcommandscopechatadministrators
""" """
type: Literal[ type: Literal[BotCommandScopeType.CHAT_ADMINISTRATORS] = (
BotCommandScopeType.CHAT_ADMINISTRATORS BotCommandScopeType.CHAT_ADMINISTRATORS
] = BotCommandScopeType.CHAT_ADMINISTRATORS )
"""Scope type, must be *chat_administrators*""" """Scope type, must be *chat_administrators*"""
chat_id: Union[int, str] chat_id: Union[int, str]
"""Unique identifier for the target chat or username of the target supergroup (in the format :code:`@supergroupusername`)""" """Unique identifier for the target chat or username of the target supergroup (in the format :code:`@supergroupusername`)"""

View file

@ -13,9 +13,9 @@ class PassportElementErrorTranslationFile(PassportElementError):
Source: https://core.telegram.org/bots/api#passportelementerrortranslationfile Source: https://core.telegram.org/bots/api#passportelementerrortranslationfile
""" """
source: Literal[ source: Literal[PassportElementErrorType.TRANSLATION_FILE] = (
PassportElementErrorType.TRANSLATION_FILE PassportElementErrorType.TRANSLATION_FILE
] = PassportElementErrorType.TRANSLATION_FILE )
"""Error source, must be *translation_file*""" """Error source, must be *translation_file*"""
type: str 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'""" """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'"""

View file

@ -13,9 +13,9 @@ class PassportElementErrorTranslationFiles(PassportElementError):
Source: https://core.telegram.org/bots/api#passportelementerrortranslationfiles Source: https://core.telegram.org/bots/api#passportelementerrortranslationfiles
""" """
source: Literal[ source: Literal[PassportElementErrorType.TRANSLATION_FILES] = (
PassportElementErrorType.TRANSLATION_FILES PassportElementErrorType.TRANSLATION_FILES
] = PassportElementErrorType.TRANSLATION_FILES )
"""Error source, must be *translation_files*""" """Error source, must be *translation_files*"""
type: str 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'""" """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'"""

View file

@ -397,8 +397,7 @@ class ReplyKeyboardBuilder(KeyboardBuilder[KeyboardButton]):
if TYPE_CHECKING: 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: def __init__(self, markup: Optional[List[List[KeyboardButton]]] = None) -> None:
super().__init__(button_type=KeyboardButton, markup=markup) super().__init__(button_type=KeyboardButton, markup=markup)

View file

@ -359,8 +359,10 @@ class MediaGroupBuilder:
update_first_media["parse_mode"] = None update_first_media["parse_mode"] = None
return [ return [
(
media.model_copy(update=update_first_media) media.model_copy(update=update_first_media)
if index == 0 and self.caption is not None if index == 0 and self.caption is not None
else media else media
)
for index, media in enumerate(self._media) for index, media in enumerate(self._media)
] ]

View file

@ -60,6 +60,7 @@ Encoding and decoding with your own methods:
# result: decoded == "foo" # result: decoded == "foo"
""" """
from base64 import urlsafe_b64decode, urlsafe_b64encode from base64 import urlsafe_b64decode, urlsafe_b64encode
from typing import Callable, Optional from typing import Callable, Optional

View file

@ -14,7 +14,7 @@ class HelloFilter(Filter):
async def __call__( async def __call__(
self, self,
message: Message, message: Message,
event_from_user: User event_from_user: User,
# Filters also can accept keyword parameters like in handlers # Filters also can accept keyword parameters like in handlers
) -> Union[bool, Dict[str, Any]]: ) -> Union[bool, Dict[str, Any]]:
if message.text.casefold() == "hello": if message.text.casefold() == "hello":

View file

@ -1,6 +1,7 @@
""" """
This example shows how to use webhook on behind of any reverse proxy (nginx, traefik, ingress etc.) This example shows how to use webhook on behind of any reverse proxy (nginx, traefik, ingress etc.)
""" """
import logging import logging
import sys import sys
from os import getenv from os import getenv

View file

@ -1,6 +1,7 @@
""" """
This example shows how to use webhook with SSL certificate. This example shows how to use webhook with SSL certificate.
""" """
import logging import logging
import ssl import ssl
import sys import sys

View file

@ -14,5 +14,4 @@ class MyFilter(Filter):
@router.message(MyFilter("hello")) @router.message(MyFilter("hello"))
async def my_handler(message: Message): async def my_handler(message: Message): ...
...

View file

@ -101,13 +101,13 @@ docs = [
"sphinxcontrib-towncrier~=0.3.2a0", "sphinxcontrib-towncrier~=0.3.2a0",
] ]
dev = [ dev = [
"black~=23.10.0", "black~=24.4.2",
"isort~=5.12.0", "isort~=5.13.2",
"ruff~=0.1.1", "ruff~=0.4.9",
"mypy~=1.6.1", "mypy~=1.10.0",
"toml~=0.10.2", "toml~=0.10.2",
"pre-commit~=3.5.0", "pre-commit~=3.5",
"packaging~=23.1", "packaging~=24.1",
"motor-types~=1.0.0b4", "motor-types~=1.0.0b4",
] ]
@ -132,10 +132,10 @@ post-install-commands = [
[tool.hatch.envs.default.scripts] [tool.hatch.envs.default.scripts]
reformat = [ reformat = [
"black aiogram tests", "black aiogram tests examples",
"isort aiogram tests", "isort aiogram tests examples",
] ]
lint = "ruff aiogram" lint = "ruff check aiogram tests examples"
[tool.hatch.envs.docs] [tool.hatch.envs.docs]
features = [ features = [
@ -202,19 +202,6 @@ python = ["38", "39", "310", "311", "312"]
[tool.ruff] [tool.ruff]
line-length = 99 line-length = 99
select = [
# "C", # TODO: mccabe - code complecity
"C4",
"E",
"F",
"T10",
"T20",
"Q",
"RET",
]
ignore = [
"F401"
]
src = ["aiogram", "tests"] src = ["aiogram", "tests"]
exclude = [ exclude = [
".git", ".git",
@ -230,7 +217,22 @@ exclude = [
] ]
target-version = "py310" 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 = [ known-first-party = [
"aiogram", "aiogram",
"finite_state_machine", "finite_state_machine",
@ -238,7 +240,7 @@ known-first-party = [
"routes", "routes",
] ]
[tool.ruff.per-file-ignores] [tool.ruff.lint.per-file-ignores]
"aiogram/client/bot.py" = ["E501"] "aiogram/client/bot.py" = ["E501"]
"aiogram/types/*" = ["E501"] "aiogram/types/*" = ["E501"]
"aiogram/methods/*" = ["E501"] "aiogram/methods/*" = ["E501"]

View file

@ -992,17 +992,13 @@ class TestDispatcher:
pytest.fail("Expected 'Detected slow response into webhook' warning.") pytest.fail("Expected 'Detected slow response into webhook' warning.")
def test_specify_updates_calculation(self): 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 = Dispatcher()
dispatcher.message.register(simple_msg_handler) dispatcher.message.register(simple_msg_handler)