From 05148e2991aff07411243b1c4dc0f8e7b0c9424e Mon Sep 17 00:00:00 2001
From: Kurosawa <145038102+KurosawaAngel@users.noreply.github.com>
Date: Mon, 4 Nov 2024 17:10:16 +0500
Subject: [PATCH 01/29] add copy text widget
---
src/aiogram_dialog/widgets/kbd/copy.py | 37 ++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
create mode 100644 src/aiogram_dialog/widgets/kbd/copy.py
diff --git a/src/aiogram_dialog/widgets/kbd/copy.py b/src/aiogram_dialog/widgets/kbd/copy.py
new file mode 100644
index 00000000..10befb2f
--- /dev/null
+++ b/src/aiogram_dialog/widgets/kbd/copy.py
@@ -0,0 +1,37 @@
+from typing import Any
+
+from aiogram.types import CopyTextButton, InlineKeyboardButton
+
+from aiogram_dialog import DialogManager
+from aiogram_dialog.api.internal import RawKeyboard
+from aiogram_dialog.widgets.common import WhenCondition
+from aiogram_dialog.widgets.kbd import Keyboard
+from aiogram_dialog.widgets.text import Text
+
+
+class CopyText(Keyboard):
+ def __init__(
+ self,
+ text: Text,
+ copy_text: Text,
+ when: WhenCondition = None,
+ ) -> None:
+ self._text = text
+ self._copy_text = copy_text
+ super().__init__(when=when)
+
+ async def _render_keyboard(
+ self,
+ data: dict[str, Any],
+ manager: DialogManager,
+ ) -> RawKeyboard:
+ return [
+ [
+ InlineKeyboardButton(
+ text=await self._text.render_text(data, manager),
+ copy_text=CopyTextButton(
+ text=await self._copy_text.render_text(data, manager),
+ ),
+ ),
+ ],
+ ]
From 6d2d8474482142894f1a82daa516f876873b7279 Mon Sep 17 00:00:00 2001
From: Kurosawa <145038102+KurosawaAngel@users.noreply.github.com>
Date: Mon, 4 Nov 2024 17:47:30 +0500
Subject: [PATCH 02/29] edit text to media
---
src/aiogram_dialog/manager/message_manager.py | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/src/aiogram_dialog/manager/message_manager.py b/src/aiogram_dialog/manager/message_manager.py
index 773c9cb2..a48d2da0 100644
--- a/src/aiogram_dialog/manager/message_manager.py
+++ b/src/aiogram_dialog/manager/message_manager.py
@@ -130,13 +130,12 @@ def _message_changed(
return False
- def _can_edit(self, new_message: NewMessage,
- old_message: OldMessage) -> bool:
+ def _can_edit(self, new_message: NewMessage, old_message: OldMessage) -> bool:
# we cannot edit message if media appeared or removed
return (
- self.had_media(old_message) == self.need_media(new_message) and
- not self.had_reply_keyboard(old_message) and
- not self.need_reply_keyboard(new_message)
+ not (self.had_media(old_message) and not self.need_media(new_message))
+ and not self.had_reply_keyboard(old_message)
+ and not self.need_reply_keyboard(new_message)
)
async def show_message(
@@ -293,7 +292,10 @@ async def edit_message(
self, bot: Bot, new_message: NewMessage, old_message: OldMessage,
) -> Message:
if new_message.media:
- if new_message.media.file_id == old_message.media_id:
+ if (
+ old_message.media_id is not None
+ and new_message.media.file_id == old_message.media_id
+ ):
return await self.edit_caption(bot, new_message, old_message)
return await self.edit_media(bot, new_message, old_message)
else:
From fbacbf9635dd8f62decdef647387df91bb0f3182 Mon Sep 17 00:00:00 2001
From: Kurosawa <145038102+KurosawaAngel@users.noreply.github.com>
Date: Mon, 4 Nov 2024 18:04:05 +0500
Subject: [PATCH 03/29] fix flake
---
src/aiogram_dialog/manager/message_manager.py | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/src/aiogram_dialog/manager/message_manager.py b/src/aiogram_dialog/manager/message_manager.py
index a48d2da0..c86879e4 100644
--- a/src/aiogram_dialog/manager/message_manager.py
+++ b/src/aiogram_dialog/manager/message_manager.py
@@ -130,13 +130,14 @@ def _message_changed(
return False
- def _can_edit(self, new_message: NewMessage, old_message: OldMessage) -> bool:
- # we cannot edit message if media appeared or removed
- return (
- not (self.had_media(old_message) and not self.need_media(new_message))
- and not self.had_reply_keyboard(old_message)
- and not self.need_reply_keyboard(new_message)
- )
+ def _can_edit(self, new_message: NewMessage,
+ old_message: OldMessage) -> bool:
+ # we cannot edit message if media appeared or remove
+ return (not (self.had_media(old_message) and
+ not self.need_media(new_message)) and
+ not self.had_reply_keyboard(old_message) and
+ not self.need_reply_keyboard(new_message)
+ )
async def show_message(
self, bot: Bot, new_message: NewMessage,
@@ -293,8 +294,8 @@ async def edit_message(
) -> Message:
if new_message.media:
if (
- old_message.media_id is not None
- and new_message.media.file_id == old_message.media_id
+ old_message.media_id is not None and
+ new_message.media.file_id == old_message.media_id
):
return await self.edit_caption(bot, new_message, old_message)
return await self.edit_media(bot, new_message, old_message)
From 8f48142e806a0a32a2ed1ce1c621110f76203bc3 Mon Sep 17 00:00:00 2001
From: Kurosawa <145038102+KurosawaAngel@users.noreply.github.com>
Date: Mon, 4 Nov 2024 18:19:00 +0500
Subject: [PATCH 04/29] add widget to __init__
---
src/aiogram_dialog/widgets/kbd/__init__.py | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/aiogram_dialog/widgets/kbd/__init__.py b/src/aiogram_dialog/widgets/kbd/__init__.py
index 07b67b98..ba4382e9 100644
--- a/src/aiogram_dialog/widgets/kbd/__init__.py
+++ b/src/aiogram_dialog/widgets/kbd/__init__.py
@@ -41,15 +41,20 @@
"ListGroup",
"ManagedListGroup",
"StubScroll",
+ "CopyText"
]
from .base import Keyboard
from .button import Button, SwitchInlineQuery, Url, WebApp
from .calendar_kbd import (
- Calendar, CalendarConfig, CalendarScope, CalendarUserConfig,
+ Calendar,
+ CalendarConfig,
+ CalendarScope,
+ CalendarUserConfig,
ManagedCalendar,
)
from .checkbox import Checkbox, ManagedCheckbox
+from .copy import CopyText
from .counter import Counter, ManagedCounter
from .group import Column, Group, Row
from .list_group import ListGroup, ManagedListGroup
From e5c45108f5c4ff08006a6000a1871e38ebc83672 Mon Sep 17 00:00:00 2001
From: Kurosawa <145038102+KurosawaAngel@users.noreply.github.com>
Date: Mon, 4 Nov 2024 23:52:00 +0500
Subject: [PATCH 05/29] better format
---
src/aiogram_dialog/manager/message_manager.py | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/src/aiogram_dialog/manager/message_manager.py b/src/aiogram_dialog/manager/message_manager.py
index c86879e4..60a7aa3f 100644
--- a/src/aiogram_dialog/manager/message_manager.py
+++ b/src/aiogram_dialog/manager/message_manager.py
@@ -132,12 +132,13 @@ def _message_changed(
def _can_edit(self, new_message: NewMessage,
old_message: OldMessage) -> bool:
- # we cannot edit message if media appeared or remove
- return (not (self.had_media(old_message) and
- not self.need_media(new_message)) and
- not self.had_reply_keyboard(old_message) and
- not self.need_reply_keyboard(new_message)
- )
+ # we cannot edit message if media removed
+ return (
+ not self.had_media(old_message) or self.need_media(new_message)
+ ) and not (
+ self.had_reply_keyboard(old_message) or
+ self.need_reply_keyboard(new_message)
+ )
async def show_message(
self, bot: Bot, new_message: NewMessage,
From c36ea7ced919910848026a47779bd1015e0c2847 Mon Sep 17 00:00:00 2001
From: Kurosawa <145038102+KurosawaAngel@users.noreply.github.com>
Date: Wed, 6 Nov 2024 02:02:34 +0500
Subject: [PATCH 06/29] BETTER CODE FORMAT
---
src/aiogram_dialog/manager/message_manager.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/aiogram_dialog/manager/message_manager.py b/src/aiogram_dialog/manager/message_manager.py
index 60a7aa3f..0c0a766d 100644
--- a/src/aiogram_dialog/manager/message_manager.py
+++ b/src/aiogram_dialog/manager/message_manager.py
@@ -133,9 +133,9 @@ def _message_changed(
def _can_edit(self, new_message: NewMessage,
old_message: OldMessage) -> bool:
# we cannot edit message if media removed
- return (
- not self.had_media(old_message) or self.need_media(new_message)
- ) and not (
+ if self.had_media(old_message) and not self.need_media(new_message):
+ return False
+ return not (
self.had_reply_keyboard(old_message) or
self.need_reply_keyboard(new_message)
)
From a727f879f38d73a25b2ebedfdbde21caa3824f6d Mon Sep 17 00:00:00 2001
From: chiri <2alivemafia@gmail.com>
Date: Wed, 6 Nov 2024 00:44:08 +0300
Subject: [PATCH 07/29] drop support python 3.8
---
.github/workflows/setup.yml | 1 -
docs/conf.py | 24 +++---
example/custom_media_url.py | 2 +-
example/i18n/bot.py | 2 +-
example/i18n/i18n_format.py | 4 +-
example/i18n/i18n_middleware.py | 7 +-
example/launch_modes.py | 2 +-
example/list_group.py | 5 +-
example/mega/bot.py | 2 +-
example/mega/bot_dialogs/calendar.py | 7 +-
example/mega/bot_dialogs/switch.py | 4 +-
pyproject.toml | 15 ++--
requirements_dev.txt | 17 -----
requirements_doc.txt | 4 -
src/aiogram_dialog/about.py | 2 +-
src/aiogram_dialog/api/entities/access.py | 4 +-
src/aiogram_dialog/api/entities/context.py | 6 +-
src/aiogram_dialog/api/entities/stack.py | 4 +-
src/aiogram_dialog/api/internal/manager.py | 4 +-
src/aiogram_dialog/api/internal/widgets.py | 11 +--
src/aiogram_dialog/api/protocols/dialog.py | 8 +-
src/aiogram_dialog/api/protocols/manager.py | 10 +--
src/aiogram_dialog/api/protocols/registry.py | 4 +-
src/aiogram_dialog/context/intent_filter.py | 4 +-
.../context/intent_middleware.py | 11 +--
src/aiogram_dialog/context/storage.py | 8 +-
src/aiogram_dialog/dialog.py | 18 ++---
src/aiogram_dialog/manager/bg_manager.py | 4 +-
src/aiogram_dialog/manager/manager.py | 12 +--
src/aiogram_dialog/manager/manager_factory.py | 4 +-
.../manager/manager_middleware.py | 13 ++--
src/aiogram_dialog/manager/sub_manager.py | 10 +--
src/aiogram_dialog/setup.py | 5 +-
src/aiogram_dialog/tools/preview.py | 32 +++++---
src/aiogram_dialog/tools/transitions.py | 8 +-
src/aiogram_dialog/utils.py | 10 +--
src/aiogram_dialog/widgets/common/__init__.py | 18 ++++-
src/aiogram_dialog/widgets/common/items.py | 7 +-
src/aiogram_dialog/widgets/common/scroll.py | 7 +-
src/aiogram_dialog/widgets/common/when.py | 12 +--
.../widgets/data/data_context.py | 6 +-
src/aiogram_dialog/widgets/input/base.py | 8 +-
src/aiogram_dialog/widgets/input/combined.py | 3 +-
src/aiogram_dialog/widgets/input/text.py | 8 +-
src/aiogram_dialog/widgets/kbd/button.py | 15 ++--
.../widgets/kbd/calendar_kbd.py | 73 ++++++++++---------
src/aiogram_dialog/widgets/kbd/checkbox.py | 7 +-
src/aiogram_dialog/widgets/kbd/counter.py | 4 +-
src/aiogram_dialog/widgets/kbd/group.py | 7 +-
src/aiogram_dialog/widgets/kbd/list_group.py | 12 ++-
src/aiogram_dialog/widgets/kbd/pager.py | 14 ++--
src/aiogram_dialog/widgets/kbd/request.py | 7 +-
.../widgets/kbd/scrolling_group.py | 12 +--
src/aiogram_dialog/widgets/kbd/select.py | 44 ++++++-----
src/aiogram_dialog/widgets/kbd/stub_scroll.py | 20 +++--
src/aiogram_dialog/widgets/media/dynamic.py | 3 +-
src/aiogram_dialog/widgets/media/scroll.py | 9 ++-
src/aiogram_dialog/widgets/text/base.py | 10 +--
src/aiogram_dialog/widgets/text/format.py | 4 +-
src/aiogram_dialog/widgets/text/jinja.py | 12 +--
src/aiogram_dialog/widgets/text/list.py | 12 ++-
src/aiogram_dialog/widgets/text/multi.py | 11 +--
src/aiogram_dialog/widgets/text/progress.py | 4 +-
.../widgets/text/scrolling_text.py | 6 +-
src/aiogram_dialog/widgets/utils.py | 11 +--
src/aiogram_dialog/widgets/widget_event.py | 3 +-
src/aiogram_dialog/window.py | 17 ++---
tests/test_click.py | 4 +-
68 files changed, 348 insertions(+), 330 deletions(-)
delete mode 100644 requirements_dev.txt
delete mode 100644 requirements_doc.txt
diff --git a/.github/workflows/setup.yml b/.github/workflows/setup.yml
index 3f4871c8..f9aeaeb7 100644
--- a/.github/workflows/setup.yml
+++ b/.github/workflows/setup.yml
@@ -21,7 +21,6 @@ jobs:
os:
- ubuntu-latest
python-version:
- - "3.8"
- "3.9"
- "3.10"
- "3.11"
diff --git a/docs/conf.py b/docs/conf.py
index 72a8a1fe..7a3178ad 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -12,32 +12,32 @@
#
# import os
# import sys
-# sys.path.insert(0, os.path.abspath('.'))
+# sys.path.insert(0, os.path.abspath("."))
import datetime
# -- Project information -----------------------------------------------------
-project = 'aiogram-dialog'
-copyright = f'{datetime.date.today().year}, Tishka17'
-author = 'Tishka17'
-master_doc = 'index'
+project = "aiogram-dialog"
+copyright = f"{datetime.date.today().year}, Tishka17"
+author = "Tishka17"
+master_doc = "index"
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
-# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# extensions coming with Sphinx (named "sphinx.ext.*") or your custom
# ones.
extensions = [
- 'sphinx.ext.autodoc',
- 'sphinx_copybutton',
+ "sphinx.ext.autodoc",
+ "sphinx_copybutton",
]
autodoc_type_aliases = {
}
-autodoc_typehints = 'description'
+autodoc_typehints = "description"
# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
+templates_path = ["_templates"]
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
@@ -49,9 +49,9 @@
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
-html_theme = 'furo'
+html_theme = "furo"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+html_static_path = ["_static"]
diff --git a/example/custom_media_url.py b/example/custom_media_url.py
index 1f169e95..19b43fde 100644
--- a/example/custom_media_url.py
+++ b/example/custom_media_url.py
@@ -115,5 +115,5 @@ async def main():
await dp.start_polling(bot)
-if __name__ == '__main__':
+if __name__ == "__main__":
asyncio.run(main())
diff --git a/example/i18n/bot.py b/example/i18n/bot.py
index d737e9d5..aa908788 100644
--- a/example/i18n/bot.py
+++ b/example/i18n/bot.py
@@ -87,5 +87,5 @@ async def main():
await dp.start_polling(bot)
-if __name__ == '__main__':
+if __name__ == "__main__":
asyncio.run(main())
diff --git a/example/i18n/i18n_format.py b/example/i18n/i18n_format.py
index 2f4cd6f2..ddf44caa 100644
--- a/example/i18n/i18n_format.py
+++ b/example/i18n/i18n_format.py
@@ -1,4 +1,4 @@
-from typing import Any, Dict, Protocol
+from typing import Any, Protocol
from aiogram_dialog.api.protocols import DialogManager
from aiogram_dialog.widgets.common import WhenCondition
@@ -21,7 +21,7 @@ def __init__(self, text: str, when: WhenCondition = None):
super().__init__(when)
self.text = text
- async def _render_text(self, data: Dict, manager: DialogManager) -> str:
+ async def _render_text(self, data: dict, manager: DialogManager) -> str:
format_text = manager.middleware_data.get(
I18N_FORMAT_KEY, default_format_text,
)
diff --git a/example/i18n/i18n_middleware.py b/example/i18n/i18n_middleware.py
index f897cb46..20fa32b2 100644
--- a/example/i18n/i18n_middleware.py
+++ b/example/i18n/i18n_middleware.py
@@ -1,4 +1,5 @@
-from typing import Any, Awaitable, Callable, Dict, Union
+from typing import Any, Union
+from collections.abc import Awaitable, Callable
from aiogram.dispatcher.middlewares.base import BaseMiddleware
from aiogram.types import CallbackQuery, Message
@@ -9,7 +10,7 @@
class I18nMiddleware(BaseMiddleware):
def __init__(
self,
- l10ns: Dict[str, FluentLocalization],
+ l10ns: dict[str, FluentLocalization],
default_lang: str,
):
super().__init__()
@@ -19,7 +20,7 @@ def __init__(
async def __call__(
self,
handler: Callable[
- [Union[Message, CallbackQuery], Dict[str, Any]],
+ [Union[Message, CallbackQuery], dict[str, Any]],
Awaitable[Any],
],
event: Union[Message, CallbackQuery],
diff --git a/example/launch_modes.py b/example/launch_modes.py
index fb94bff3..f68f63f4 100644
--- a/example/launch_modes.py
+++ b/example/launch_modes.py
@@ -93,5 +93,5 @@ async def main():
await dp.start_polling(bot)
-if __name__ == '__main__':
+if __name__ == "__main__":
asyncio.run(main())
diff --git a/example/list_group.py b/example/list_group.py
index e791a24b..a66a18ba 100644
--- a/example/list_group.py
+++ b/example/list_group.py
@@ -1,7 +1,6 @@
import asyncio
import logging
import os
-from typing import Dict
from aiogram import Bot, Dispatcher
from aiogram.filters import CommandStart
@@ -27,7 +26,7 @@ class DialogSG(StatesGroup):
greeting = State()
-def when_checked(data: Dict, widget, manager: SubManager) -> bool:
+def when_checked(data: dict, widget, manager: SubManager) -> bool:
# manager for our case is already adapted for current ListGroup row
# so `.find` returns widget adapted for current row
# if you need to find widgets outside the row, use `.find_in_parent`
@@ -98,5 +97,5 @@ async def main():
await dp.start_polling(bot)
-if __name__ == '__main__':
+if __name__ == "__main__":
asyncio.run(main())
diff --git a/example/mega/bot.py b/example/mega/bot.py
index d373b80b..11d43bb7 100644
--- a/example/mega/bot.py
+++ b/example/mega/bot.py
@@ -93,5 +93,5 @@ async def main():
await dp.start_polling(bot)
-if __name__ == '__main__':
+if __name__ == "__main__":
asyncio.run(main())
diff --git a/example/mega/bot_dialogs/calendar.py b/example/mega/bot_dialogs/calendar.py
index 5101b89c..4f1bbe14 100644
--- a/example/mega/bot_dialogs/calendar.py
+++ b/example/mega/bot_dialogs/calendar.py
@@ -1,5 +1,4 @@
from datetime import date
-from typing import Dict
from aiogram import F
from babel.dates import get_day_names, get_month_names
@@ -25,7 +24,7 @@ async def _render_text(self, data, manager: DialogManager) -> str:
selected_date: date = data["date"]
locale = manager.event.from_user.language_code
return get_day_names(
- width="short", context='stand-alone', locale=locale,
+ width="short", context="stand-alone", locale=locale,
)[selected_date.weekday()].title()
@@ -49,12 +48,12 @@ async def _render_text(self, data, manager: DialogManager) -> str:
selected_date: date = data["date"]
locale = manager.event.from_user.language_code
return get_month_names(
- 'wide', context='stand-alone', locale=locale,
+ "wide", context="stand-alone", locale=locale,
)[selected_date.month].title()
class CustomCalendar(Calendar):
- def _init_views(self) -> Dict[CalendarScope, CalendarScopeView]:
+ def _init_views(self) -> dict[CalendarScope, CalendarScopeView]:
return {
CalendarScope.DAYS: CalendarDaysView(
self._item_callback_data,
diff --git a/example/mega/bot_dialogs/switch.py b/example/mega/bot_dialogs/switch.py
index 80cbd0a2..faf3a4d0 100644
--- a/example/mega/bot_dialogs/switch.py
+++ b/example/mega/bot_dialogs/switch.py
@@ -1,4 +1,4 @@
-from typing import Any, Dict
+from typing import Any
from aiogram_dialog import Dialog, DialogManager, Window
from aiogram_dialog.widgets.kbd import Back, Checkbox, Next, Radio, Row
@@ -14,7 +14,7 @@
async def data_getter(
dialog_manager: DialogManager, **_kwargs,
-) -> Dict[str, Any]:
+) -> dict[str, Any]:
return {
"option": dialog_manager.find(CHECKBOX_ID).is_checked(),
"emoji": dialog_manager.find(EMOJI_ID).get_checked(),
diff --git a/pyproject.toml b/pyproject.toml
index 8063d94b..84c18f36 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,5 +1,5 @@
[build-system]
-requires = ["setuptools>=66.0"]
+requires = ["setuptools==75.3.0"]
build-backend = "setuptools.build_meta"
[tool.setuptools]
@@ -17,18 +17,21 @@ authors = [
]
license = { text = "Apache-2.0" }
description = "Telegram bot UI framework on top of aiogram"
-requires-python = ">=3.8"
+requires-python = ">=3.9"
classifiers = [
"Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent",
]
dependencies = [
- 'aiogram>=3.5.0',
- 'jinja2',
- 'cachetools>=4.0.0,<6.0.0',
- 'magic_filter',
+ "aiogram>=3.14.0",
+ "jinja2",
+ "cachetools>=4.0.0,<6.0.0",
]
[project.optional-dependencies]
tools = [
diff --git a/requirements_dev.txt b/requirements_dev.txt
deleted file mode 100644
index faf62be7..00000000
--- a/requirements_dev.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-vulture
-flake8==7.*
-flake8-blind-except
-flake8-bugbear
-flake8-builtins
-flake8-cognitive-complexity
-flake8-comprehensions
-flake8-docstrings
-flake8-eradicate
-flake8-import-order
-flake8-mutable
-flake8-polyfill
-flake8-print
-
-pytest
-pytest-asyncio
-pytest-repeat
diff --git a/requirements_doc.txt b/requirements_doc.txt
deleted file mode 100644
index 54e78bcc..00000000
--- a/requirements_doc.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-sphinx
-sphinx-autodocgen
-furo
-sphinx-copybutton
diff --git a/src/aiogram_dialog/about.py b/src/aiogram_dialog/about.py
index fe0baced..c4162512 100644
--- a/src/aiogram_dialog/about.py
+++ b/src/aiogram_dialog/about.py
@@ -33,7 +33,7 @@ def about_dialog():
"Author: {{metadata['Author-email']}}\n"
"\n"
"{% for name, url in urls%}"
- "{{name}}: {{url}}\n"
+ '{{name}}: {{url}}\n'
"{% endfor %}"
"",
),
diff --git a/src/aiogram_dialog/api/entities/access.py b/src/aiogram_dialog/api/entities/access.py
index bf49c19f..158b7926 100644
--- a/src/aiogram_dialog/api/entities/access.py
+++ b/src/aiogram_dialog/api/entities/access.py
@@ -1,8 +1,8 @@
from dataclasses import dataclass
-from typing import Any, List
+from typing import Any
@dataclass
class AccessSettings:
- user_ids: List[int]
+ user_ids: list[int]
custom: Any = None
diff --git a/src/aiogram_dialog/api/entities/context.py b/src/aiogram_dialog/api/entities/context.py
index b4882088..0f48af41 100644
--- a/src/aiogram_dialog/api/entities/context.py
+++ b/src/aiogram_dialog/api/entities/context.py
@@ -1,12 +1,12 @@
from dataclasses import dataclass, field
-from typing import Dict, List, Optional, Union
+from typing import Optional, Union
from aiogram.fsm.state import State
from .access import AccessSettings
-Data = Union[Dict, List, int, str, float, None]
-DataDict = Dict[str, Data]
+Data = Union[dict, list, int, str, float, None]
+DataDict = dict[str, Data]
@dataclass(unsafe_hash=True)
diff --git a/src/aiogram_dialog/api/entities/stack.py b/src/aiogram_dialog/api/entities/stack.py
index 30fbd8cb..824830b1 100644
--- a/src/aiogram_dialog/api/entities/stack.py
+++ b/src/aiogram_dialog/api/entities/stack.py
@@ -2,7 +2,7 @@
import string
import time
from dataclasses import dataclass, field
-from typing import List, Optional
+from typing import Optional
from aiogram.fsm.state import State
@@ -38,7 +38,7 @@ def new_id():
@dataclass(unsafe_hash=True)
class Stack:
_id: str = field(compare=True, default_factory=new_id)
- intents: List[str] = field(compare=False, default_factory=list)
+ intents: list[str] = field(compare=False, default_factory=list)
last_message_id: Optional[int] = field(compare=False, default=None)
last_reply_keyboard: bool = field(compare=False, default=False)
last_media_id: Optional[str] = field(compare=False, default=None)
diff --git a/src/aiogram_dialog/api/internal/manager.py b/src/aiogram_dialog/api/internal/manager.py
index 73e399c5..145743c2 100644
--- a/src/aiogram_dialog/api/internal/manager.py
+++ b/src/aiogram_dialog/api/internal/manager.py
@@ -1,5 +1,5 @@
from abc import abstractmethod
-from typing import Dict, Protocol
+from typing import Protocol
from aiogram import Router
@@ -12,7 +12,7 @@
class DialogManagerFactory(Protocol):
@abstractmethod
def __call__(
- self, event: ChatEvent, data: Dict,
+ self, event: ChatEvent, data: dict,
registry: DialogRegistryProtocol,
router: Router,
) -> DialogManager:
diff --git a/src/aiogram_dialog/api/internal/widgets.py b/src/aiogram_dialog/api/internal/widgets.py
index df306af8..ba51d328 100644
--- a/src/aiogram_dialog/api/internal/widgets.py
+++ b/src/aiogram_dialog/api/internal/widgets.py
@@ -1,8 +1,9 @@
from abc import abstractmethod
from typing import (
- Any, Awaitable, Callable, Dict, List, Optional, Protocol,
+ Any, Optional, Protocol,
runtime_checkable, Union,
)
+from collections.abc import Awaitable, Callable
from aiogram.types import (
CallbackQuery, InlineKeyboardButton, KeyboardButton, Message,
@@ -28,21 +29,21 @@ def find(self, widget_id: str) -> Optional["Widget"]:
class TextWidget(Widget, Protocol):
@abstractmethod
async def render_text(
- self, data: Dict, manager: DialogManager,
+ self, data: dict, manager: DialogManager,
) -> str:
"""Create text."""
raise NotImplementedError
ButtonVariant = Union[InlineKeyboardButton, KeyboardButton]
-RawKeyboard = List[List[ButtonVariant]]
+RawKeyboard = list[list[ButtonVariant]]
@runtime_checkable
class KeyboardWidget(Widget, Protocol):
@abstractmethod
async def render_keyboard(
- self, data: Dict, manager: DialogManager,
+ self, data: dict, manager: DialogManager,
) -> RawKeyboard:
"""Create Inline keyboard contents."""
raise NotImplementedError
@@ -89,7 +90,7 @@ async def process_message(
raise NotImplementedError
-DataGetter = Callable[..., Awaitable[Dict]]
+DataGetter = Callable[..., Awaitable[dict]]
@runtime_checkable
diff --git a/src/aiogram_dialog/api/protocols/dialog.py b/src/aiogram_dialog/api/protocols/dialog.py
index 941566dd..5960aa37 100644
--- a/src/aiogram_dialog/api/protocols/dialog.py
+++ b/src/aiogram_dialog/api/protocols/dialog.py
@@ -1,5 +1,5 @@
from abc import abstractmethod
-from typing import Any, Dict, List, Optional, Protocol, runtime_checkable, Type
+from typing import Any, Optional, Protocol, runtime_checkable
from aiogram.fsm.state import State, StatesGroup
@@ -24,11 +24,11 @@ def states_group_name(self) -> str:
raise NotImplementedError
@abstractmethod
- def states(self) -> List[State]:
+ def states(self) -> list[State]:
raise NotImplementedError
@abstractmethod
- def states_group(self) -> Type[StatesGroup]:
+ def states_group(self) -> type[StatesGroup]:
raise NotImplementedError
@abstractmethod
@@ -60,7 +60,7 @@ def find(self, widget_id) -> Any:
@abstractmethod
async def load_data(
self, manager: DialogManager,
- ) -> Dict:
+ ) -> dict:
raise NotImplementedError
@abstractmethod
diff --git a/src/aiogram_dialog/api/protocols/manager.py b/src/aiogram_dialog/api/protocols/manager.py
index 899c7e5e..e578ecc5 100644
--- a/src/aiogram_dialog/api/protocols/manager.py
+++ b/src/aiogram_dialog/api/protocols/manager.py
@@ -1,6 +1,6 @@
from abc import abstractmethod
from enum import Enum
-from typing import Any, Dict, Optional, Protocol, Union
+from typing import Any, Optional, Protocol, Union
from aiogram import Bot
from aiogram.fsm.state import State
@@ -46,7 +46,7 @@ async def switch_to(
@abstractmethod
async def update(
self,
- data: Dict,
+ data: dict,
show_mode: Optional[ShowMode] = None,
) -> None:
raise NotImplementedError
@@ -91,13 +91,13 @@ async def mark_closed(self) -> None:
@property
@abstractmethod
- def middleware_data(self) -> Dict:
+ def middleware_data(self) -> dict:
"""Middleware data."""
raise NotImplementedError
@property
@abstractmethod
- def dialog_data(self) -> Dict:
+ def dialog_data(self) -> dict:
"""Dialog data for current context."""
raise NotImplementedError
@@ -183,7 +183,7 @@ async def reset_stack(self, remove_keyboard: bool = True) -> None:
raise NotImplementedError
@abstractmethod
- async def load_data(self) -> Dict:
+ async def load_data(self) -> dict:
"""Load data for current state."""
raise NotImplementedError
diff --git a/src/aiogram_dialog/api/protocols/registry.py b/src/aiogram_dialog/api/protocols/registry.py
index 5608c801..6a59095a 100644
--- a/src/aiogram_dialog/api/protocols/registry.py
+++ b/src/aiogram_dialog/api/protocols/registry.py
@@ -1,5 +1,5 @@
from abc import abstractmethod
-from typing import Dict, Protocol, Type, Union
+from typing import Protocol, Union
from aiogram.fsm.state import State, StatesGroup
@@ -12,5 +12,5 @@ def find_dialog(self, state: Union[State, str]) -> DialogProtocol:
raise NotImplementedError
@abstractmethod
- def states_groups(self) -> Dict[str, Type[StatesGroup]]:
+ def states_groups(self) -> dict[str, type[StatesGroup]]:
raise NotImplementedError
diff --git a/src/aiogram_dialog/context/intent_filter.py b/src/aiogram_dialog/context/intent_filter.py
index 29309fdf..c38da0ec 100644
--- a/src/aiogram_dialog/context/intent_filter.py
+++ b/src/aiogram_dialog/context/intent_filter.py
@@ -1,4 +1,4 @@
-from typing import Optional, Type
+from typing import Optional
from aiogram.filters import BaseFilter
from aiogram.fsm.state import StatesGroup
@@ -9,7 +9,7 @@
class IntentFilter(BaseFilter):
- def __init__(self, aiogd_intent_state_group: Optional[Type[StatesGroup]]):
+ def __init__(self, aiogd_intent_state_group: Optional[type[StatesGroup]]):
self.aiogd_intent_state_group = aiogd_intent_state_group
async def __call__(self, obj: TelegramObject, **kwargs) -> bool:
diff --git a/src/aiogram_dialog/context/intent_middleware.py b/src/aiogram_dialog/context/intent_middleware.py
index b781fa41..f19cc7a1 100644
--- a/src/aiogram_dialog/context/intent_middleware.py
+++ b/src/aiogram_dialog/context/intent_middleware.py
@@ -1,5 +1,6 @@
from logging import getLogger
-from typing import Any, Awaitable, Callable, Dict, Optional
+from typing import Any, Optional
+from collections.abc import Awaitable, Callable
from aiogram import Router
from aiogram.dispatcher.event.bases import UNHANDLED
@@ -159,7 +160,7 @@ def _check_outdated(self, intent_id: str, stack: Stack):
f"Outdated intent id ({intent_id}) "
f"for stack ({stack.id})",
)
- elif intent_id != stack.last_intent_id():
+ if intent_id != stack.last_intent_id():
raise OutdatedIntent(
stack.id,
f"Outdated intent id ({intent_id}) "
@@ -444,7 +445,7 @@ def __init__(
self.access_validator = access_validator
def _is_error_supported(
- self, event: ErrorEvent, data: Dict[str, Any],
+ self, event: ErrorEvent, data: dict[str, Any],
) -> bool:
if isinstance(event, InvalidStackIdError):
return False
@@ -487,10 +488,10 @@ async def _load_stack(
async def __call__(
self,
handler: Callable[
- [ErrorEvent, Dict[str, Any]], Awaitable[Any],
+ [ErrorEvent, dict[str, Any]], Awaitable[Any],
],
event: ErrorEvent,
- data: Dict[str, Any],
+ data: dict[str, Any],
) -> Any:
error = event.exception
if not self._is_error_supported(event, data):
diff --git a/src/aiogram_dialog/context/storage.py b/src/aiogram_dialog/context/storage.py
index 1269008a..b6c39e7d 100644
--- a/src/aiogram_dialog/context/storage.py
+++ b/src/aiogram_dialog/context/storage.py
@@ -1,6 +1,6 @@
from contextlib import AsyncExitStack
from copy import copy
-from typing import Dict, Optional, Type
+from typing import Optional
from aiogram import Bot
from aiogram.fsm.state import State, StatesGroup
@@ -24,7 +24,7 @@ def __init__(
thread_id: Optional[int],
business_connection_id: Optional[str],
bot: Bot,
- state_groups: Dict[str, Type[StatesGroup]],
+ state_groups: dict[str, type[StatesGroup]],
):
self.storage = storage
self.events_isolation = events_isolation
@@ -164,7 +164,7 @@ def _state(self, state: str) -> State:
raise UnknownState(f"Unknown state {state}")
def _parse_access_settings(
- self, raw: Optional[Dict],
+ self, raw: Optional[dict],
) -> Optional[AccessSettings]:
if not raw:
return None
@@ -175,7 +175,7 @@ def _parse_access_settings(
def _dump_access_settings(
self, access_settings: Optional[AccessSettings],
- ) -> Optional[Dict]:
+ ) -> Optional[dict]:
if not access_settings:
return None
return {
diff --git a/src/aiogram_dialog/dialog.py b/src/aiogram_dialog/dialog.py
index 164d045c..5da26c73 100644
--- a/src/aiogram_dialog/dialog.py
+++ b/src/aiogram_dialog/dialog.py
@@ -1,12 +1,8 @@
+from collections.abc import Awaitable, Callable
from logging import getLogger
from typing import (
Any,
- Awaitable,
- Callable,
- Dict,
- List,
Optional,
- Type,
TypeVar,
Union,
)
@@ -51,7 +47,7 @@ def __init__(
):
super().__init__(name=name or windows[0].get_state().group.__name__)
self._states_group = windows[0].get_state().group
- self._states: List[State] = []
+ self._states: list[State] = []
for w in windows:
if w.get_state().group != self._states_group:
raise ValueError(
@@ -61,8 +57,8 @@ def __init__(
if state in self._states:
raise ValueError(f"Multiple windows with state {state}")
self._states.append(state)
- self.windows: Dict[State, WindowProtocol] = dict(
- zip(self._states, windows),
+ self.windows: dict[State, WindowProtocol] = dict(
+ zip(self._states, windows, strict=False),
)
self.on_start = on_start
self.on_close = on_close
@@ -79,7 +75,7 @@ def __init__(
def launch_mode(self) -> LaunchMode:
return self._launch_mode
- def states(self) -> List[State]:
+ def states(self) -> list[State]:
return self._states
async def process_start(
@@ -113,7 +109,7 @@ async def _current_window(
async def load_data(
self, manager: DialogManager,
- ) -> Dict:
+ ) -> dict:
data = await manager.load_data()
data.update(await self.getter(**manager.middleware_data))
return data
@@ -188,7 +184,7 @@ def _register_handlers(self) -> None:
self.callback_query.register(self._callback_handler)
self.message.register(self._message_handler)
- def states_group(self) -> Type[StatesGroup]:
+ def states_group(self) -> type[StatesGroup]:
return self._states_group
def states_group_name(self) -> str:
diff --git a/src/aiogram_dialog/manager/bg_manager.py b/src/aiogram_dialog/manager/bg_manager.py
index 4e4adb34..dfd05c74 100644
--- a/src/aiogram_dialog/manager/bg_manager.py
+++ b/src/aiogram_dialog/manager/bg_manager.py
@@ -1,5 +1,5 @@
from logging import getLogger
-from typing import Any, Dict, Optional, Union
+from typing import Any, Optional, Union
from aiogram import Bot, Router
from aiogram.fsm.state import State
@@ -241,7 +241,7 @@ async def switch_to(
async def update(
self,
- data: Dict,
+ data: dict,
show_mode: Optional[ShowMode] = None,
) -> None:
await self._load()
diff --git a/src/aiogram_dialog/manager/manager.py b/src/aiogram_dialog/manager/manager.py
index fc984f13..b310b381 100644
--- a/src/aiogram_dialog/manager/manager.py
+++ b/src/aiogram_dialog/manager/manager.py
@@ -1,6 +1,6 @@
from copy import deepcopy
from logging import getLogger
-from typing import Any, cast, Dict, Optional, Union
+from typing import Any, cast, Optional, Union
from aiogram import Router
from aiogram.enums import ChatType
@@ -55,7 +55,7 @@ def __init__(
media_id_storage: MediaIdStorageProtocol,
registry: DialogRegistryProtocol,
router: Router,
- data: Dict,
+ data: dict,
):
self.disabled = False
self.message_manager = message_manager
@@ -81,12 +81,12 @@ def event(self) -> ChatEvent:
return self._event
@property
- def middleware_data(self) -> Dict:
+ def middleware_data(self) -> dict:
"""Middleware data."""
return self._data
@property
- def dialog_data(self) -> Dict:
+ def dialog_data(self) -> dict:
"""Dialog data for current context."""
return self.current_context().dialog_data
@@ -103,7 +103,7 @@ def check_disabled(self):
"method to access methods from background tasks",
)
- async def load_data(self) -> Dict:
+ async def load_data(self) -> dict:
context = self.current_context()
return {
"dialog_data": context.dialog_data,
@@ -468,7 +468,7 @@ def _calc_show_mode(self) -> ShowMode:
async def update(
self,
- data: Dict,
+ data: dict,
show_mode: Optional[ShowMode] = None,
) -> None:
self.current_context().dialog_data.update(data)
diff --git a/src/aiogram_dialog/manager/manager_factory.py b/src/aiogram_dialog/manager/manager_factory.py
index a42f157c..aafa263a 100644
--- a/src/aiogram_dialog/manager/manager_factory.py
+++ b/src/aiogram_dialog/manager/manager_factory.py
@@ -1,5 +1,3 @@
-from typing import Dict
-
from aiogram import Router
from aiogram_dialog.api.entities import ChatEvent
@@ -21,7 +19,7 @@ def __init__(
self.media_id_storage = media_id_storage
def __call__(
- self, event: ChatEvent, data: Dict,
+ self, event: ChatEvent, data: dict,
registry: DialogRegistryProtocol,
router: Router,
) -> DialogManager:
diff --git a/src/aiogram_dialog/manager/manager_middleware.py b/src/aiogram_dialog/manager/manager_middleware.py
index 4d9d4829..2166eaae 100644
--- a/src/aiogram_dialog/manager/manager_middleware.py
+++ b/src/aiogram_dialog/manager/manager_middleware.py
@@ -1,4 +1,5 @@
-from typing import Any, Awaitable, Callable, Dict, Union
+from typing import Any, Union
+from collections.abc import Awaitable, Callable
from aiogram import Router
from aiogram.dispatcher.middlewares.base import BaseMiddleware
@@ -27,18 +28,18 @@ def __init__(
self.router = router
def _is_event_supported(
- self, event: TelegramObject, data: Dict[str, Any],
+ self, event: TelegramObject, data: dict[str, Any],
) -> bool:
return STORAGE_KEY in data
async def __call__(
self,
handler: Callable[
- [Union[Update, DialogUpdateEvent], Dict[str, Any]],
+ [Union[Update, DialogUpdateEvent], dict[str, Any]],
Awaitable[Any],
],
event: ChatEvent,
- data: Dict[str, Any],
+ data: dict[str, Any],
) -> Any:
if self._is_event_supported(event, data):
data[MANAGER_KEY] = self.dialog_manager_factory(
@@ -67,11 +68,11 @@ def __init__(
async def __call__(
self,
handler: Callable[
- [Union[TelegramObject, DialogUpdateEvent], Dict[str, Any]],
+ [Union[TelegramObject, DialogUpdateEvent], dict[str, Any]],
Awaitable[TelegramObject],
],
event: TelegramObject,
- data: Dict[str, Any],
+ data: dict[str, Any],
) -> Any:
data[BG_FACTORY_KEY] = self.bg_manager_factory
return await handler(event, data)
diff --git a/src/aiogram_dialog/manager/sub_manager.py b/src/aiogram_dialog/manager/sub_manager.py
index 86069a34..6767e6dc 100644
--- a/src/aiogram_dialog/manager/sub_manager.py
+++ b/src/aiogram_dialog/manager/sub_manager.py
@@ -1,5 +1,5 @@
import dataclasses
-from typing import Any, Dict, Optional, Union
+from typing import Any, Optional, Union
from aiogram.fsm.state import State
from aiogram.types import Message
@@ -33,12 +33,12 @@ def event(self) -> ChatEvent:
return self.manager.event
@property
- def middleware_data(self) -> Dict:
+ def middleware_data(self) -> dict:
"""Middleware data."""
return self.manager.middleware_data
@property
- def dialog_data(self) -> Dict:
+ def dialog_data(self) -> dict:
"""Dialog data for current context."""
return self.current_context().dialog_data
@@ -74,7 +74,7 @@ async def answer_callback(self) -> None:
async def reset_stack(self, remove_keyboard: bool = True) -> None:
return await self.manager.reset_stack(remove_keyboard)
- async def load_data(self) -> Dict:
+ async def load_data(self) -> dict:
return await self.manager.load_data()
def find(self, widget_id) -> Optional[Any]:
@@ -133,7 +133,7 @@ async def switch_to(
async def update(
self,
- data: Dict,
+ data: dict,
show_mode: Optional[ShowMode] = None,
) -> None:
self.current_context().dialog_data.update(data)
diff --git a/src/aiogram_dialog/setup.py b/src/aiogram_dialog/setup.py
index c7825799..7eb5eac5 100644
--- a/src/aiogram_dialog/setup.py
+++ b/src/aiogram_dialog/setup.py
@@ -1,4 +1,5 @@
-from typing import Callable, Dict, Iterable, Optional, Type, Union
+from typing import Optional, Union
+from collections.abc import Callable, Iterable
from aiogram import Router
from aiogram.dispatcher.event.telegram import TelegramEventObserver
@@ -63,7 +64,7 @@ def find_dialog(self, state: Union[State, str]) -> DialogProtocol:
f" (looking by state `{state}`)",
) from e
- def states_groups(self) -> Dict[str, Type[StatesGroup]]:
+ def states_groups(self) -> dict[str, type[StatesGroup]]:
self._ensure_loaded()
return self._states_groups
diff --git a/src/aiogram_dialog/tools/preview.py b/src/aiogram_dialog/tools/preview.py
index 63b24188..aa2ae080 100644
--- a/src/aiogram_dialog/tools/preview.py
+++ b/src/aiogram_dialog/tools/preview.py
@@ -2,18 +2,26 @@
import logging
from dataclasses import dataclass
from datetime import datetime
-from typing import Any, Dict, List, Optional, Type, Union
+from typing import Any, Optional, Union
from aiogram import Router
from aiogram.fsm.state import State, StatesGroup
from aiogram.types import (
- CallbackQuery, Chat, ContentType, InlineKeyboardMarkup, Message,
- ReplyKeyboardMarkup, User,
+ CallbackQuery,
+ Chat,
+ ContentType,
+ InlineKeyboardMarkup,
+ Message,
+ ReplyKeyboardMarkup,
+ User,
)
from jinja2 import Environment, PackageLoader, select_autoescape
from aiogram_dialog import (
- BaseDialogManager, Dialog, DialogManager, DialogProtocol,
+ BaseDialogManager,
+ Dialog,
+ DialogManager,
+ DialogProtocol,
)
from aiogram_dialog.api.entities import (
AccessSettings,
@@ -47,8 +55,8 @@ class RenderWindow:
message: str
state: str
state_name: str
- keyboard: List[List[RenderButton]]
- reply_keyboard: List[List[RenderButton]]
+ keyboard: list[list[RenderButton]]
+ reply_keyboard: list[list[RenderButton]]
photo: Optional[str]
text_input: Optional[RenderButton]
attachment_input: Optional[RenderButton]
@@ -57,7 +65,7 @@ class RenderWindow:
@dataclass
class RenderDialog:
state_group: str
- windows: List[RenderWindow]
+ windows: list[RenderWindow]
class FakeManager(DialogManager):
@@ -104,14 +112,14 @@ async def back(self, show_mode: Optional[ShowMode] = None) -> None:
await self.switch_to(new_state, show_mode)
@property
- def middleware_data(self) -> Dict:
+ def middleware_data(self) -> dict:
return self._data
@property
def event(self) -> ChatEvent:
return self._event
- async def load_data(self) -> Dict:
+ async def load_data(self) -> dict:
return {}
async def close_manager(self) -> None:
@@ -131,7 +139,7 @@ def is_preview(self) -> bool:
return True
@property
- def dialog_data(self) -> Dict:
+ def dialog_data(self) -> dict:
return self.current_context().dialog_data
def reset_context(self) -> None:
@@ -208,7 +216,7 @@ def find(self, widget_id) -> Optional[Any]:
async def update(
self,
- data: Dict,
+ data: dict,
show_mode: Optional[ShowMode] = None,
) -> None:
pass
@@ -408,7 +416,7 @@ async def create_window(
async def render_dialog(
manager: FakeManager,
- group: Type[StatesGroup],
+ group: type[StatesGroup],
dialog: Dialog,
simulate_events: bool,
) -> RenderDialog:
diff --git a/src/aiogram_dialog/tools/transitions.py b/src/aiogram_dialog/tools/transitions.py
index 161dd32d..3706658d 100644
--- a/src/aiogram_dialog/tools/transitions.py
+++ b/src/aiogram_dialog/tools/transitions.py
@@ -1,5 +1,5 @@
import os.path
-from typing import Iterable, List, Sequence, Tuple
+from collections.abc import Iterable, Sequence
from aiogram import Router
from aiogram.fsm.state import State
@@ -46,7 +46,7 @@ def widget_edges(nodes, dialog, starts, current_state, kbd):
def walk_keyboard(
nodes,
dialog,
- starts: List[Tuple[State, State]],
+ starts: list[tuple[State, State]],
current_state: State,
keyboards: Sequence,
):
@@ -59,7 +59,7 @@ def walk_keyboard(
def find_starts(
current_state, keyboards: Sequence,
-) -> Iterable[Tuple[State, State]]:
+) -> Iterable[tuple[State, State]]:
for kbd in keyboards:
if isinstance(kbd, Group):
yield from find_starts(current_state, kbd.buttons)
@@ -68,7 +68,7 @@ def find_starts(
def render_window(
- nodes: dict, dialog: Dialog, starts: List[Tuple[State, State]],
+ nodes: dict, dialog: Dialog, starts: list[tuple[State, State]],
window: WindowProtocol,
):
walk_keyboard(
diff --git a/src/aiogram_dialog/utils.py b/src/aiogram_dialog/utils.py
index 17682f63..023b4a77 100644
--- a/src/aiogram_dialog/utils.py
+++ b/src/aiogram_dialog/utils.py
@@ -1,5 +1,5 @@
from logging import getLogger
-from typing import List, Optional, Tuple, Union
+from typing import Optional, Union
from aiogram.types import (
CallbackQuery,
@@ -70,7 +70,7 @@ def join_reply_callback(text: str, callback_data: str) -> str:
def split_reply_callback(
data: Optional[str],
-) -> Tuple[Optional[str], Optional[str]]:
+) -> tuple[Optional[str], Optional[str]]:
if not data:
return None, None
text = data.rstrip(REPLY_CALLBACK_SYMBOLS)
@@ -103,8 +103,8 @@ def _transform_to_reply_button(
def transform_to_reply_keyboard(
- keyboard: List[List[Union[InlineKeyboardButton, KeyboardButton]]],
-) -> List[List[KeyboardButton]]:
+ keyboard: list[list[Union[InlineKeyboardButton, KeyboardButton]]],
+) -> list[list[KeyboardButton]]:
new_kdb = []
for row in keyboard:
new_row = []
@@ -186,7 +186,7 @@ def add_intent_id(keyboard: RawKeyboard, intent_id: str):
)
-def remove_intent_id(callback_data: str) -> Tuple[Optional[str], str]:
+def remove_intent_id(callback_data: str) -> tuple[Optional[str], str]:
if CB_SEP in callback_data:
intent_id, new_data = callback_data.split(CB_SEP, maxsplit=1)
return intent_id, new_data
diff --git a/src/aiogram_dialog/widgets/common/__init__.py b/src/aiogram_dialog/widgets/common/__init__.py
index 7f0dd208..bc59f780 100644
--- a/src/aiogram_dialog/widgets/common/__init__.py
+++ b/src/aiogram_dialog/widgets/common/__init__.py
@@ -2,16 +2,26 @@
"Actionable",
"BaseWidget",
"ManagedWidget",
- "BaseScroll", "ManagedScroll",
- "OnPageChanged", "OnPageChangedVariants", "Scroll", "sync_scroll",
- "true_condition", "Whenable", "WhenCondition",
+ "BaseScroll",
+ "ManagedScroll",
+ "OnPageChanged",
+ "OnPageChangedVariants",
+ "Scroll",
+ "sync_scroll",
+ "true_condition",
+ "Whenable",
+ "WhenCondition",
]
from .action import Actionable
from .base import BaseWidget
from .managed import ManagedWidget
from .scroll import (
- BaseScroll, ManagedScroll, OnPageChanged, OnPageChangedVariants, Scroll,
+ BaseScroll,
+ ManagedScroll,
+ OnPageChanged,
+ OnPageChangedVariants,
+ Scroll,
sync_scroll,
)
from .when import true_condition, Whenable, WhenCondition
diff --git a/src/aiogram_dialog/widgets/common/items.py b/src/aiogram_dialog/widgets/common/items.py
index 211a5b11..bac707ac 100644
--- a/src/aiogram_dialog/widgets/common/items.py
+++ b/src/aiogram_dialog/widgets/common/items.py
@@ -1,9 +1,10 @@
from operator import itemgetter
-from typing import Callable, Dict, Sequence, Union
+from typing import Union
+from collections.abc import Callable, Sequence
from magic_filter import MagicFilter
-ItemsGetter = Callable[[Dict], Sequence]
+ItemsGetter = Callable[[dict], Sequence]
ItemsGetterVariant = Union[str, ItemsGetter, MagicFilter, Sequence]
@@ -15,7 +16,7 @@ def identity(data) -> Sequence:
def _get_magic_getter(f: MagicFilter) -> ItemsGetter:
- def items_magic(data: Dict) -> Sequence:
+ def items_magic(data: dict) -> Sequence:
items = f.resolve(data)
if isinstance(items, Sequence):
return items
diff --git a/src/aiogram_dialog/widgets/common/scroll.py b/src/aiogram_dialog/widgets/common/scroll.py
index 5c1ceb86..bd9e0e9e 100644
--- a/src/aiogram_dialog/widgets/common/scroll.py
+++ b/src/aiogram_dialog/widgets/common/scroll.py
@@ -1,5 +1,6 @@
from abc import ABC, abstractmethod
-from typing import Awaitable, Callable, Dict, Protocol, Sequence, Union
+from typing import Protocol, Union
+from collections.abc import Awaitable, Callable, Sequence
from aiogram_dialog.api.entities import ChatEvent
from aiogram_dialog.api.internal import Widget
@@ -13,7 +14,7 @@
class Scroll(Widget, Protocol):
@abstractmethod
- async def get_page_count(self, data: Dict, manager: DialogManager) -> int:
+ async def get_page_count(self, data: dict, manager: DialogManager) -> int:
raise NotImplementedError
@abstractmethod
@@ -32,7 +33,7 @@ def managed(self, manager: DialogManager) -> "ManagedScroll":
class ManagedScroll(ManagedWidget[Scroll]):
- async def get_page_count(self, data: Dict) -> int:
+ async def get_page_count(self, data: dict) -> int:
return await self.widget.get_page_count(data, self.manager)
async def get_page(self) -> int:
diff --git a/src/aiogram_dialog/widgets/common/when.py b/src/aiogram_dialog/widgets/common/when.py
index fec1eb81..24bf39d6 100644
--- a/src/aiogram_dialog/widgets/common/when.py
+++ b/src/aiogram_dialog/widgets/common/when.py
@@ -1,7 +1,7 @@
from __future__ import annotations
from abc import abstractmethod
-from typing import Dict, Protocol, Union
+from typing import Protocol, Union
from magic_filter import MagicFilter
@@ -12,7 +12,7 @@ class Predicate(Protocol):
@abstractmethod
def __call__(
self,
- data: Dict,
+ data: dict,
widget: Whenable,
dialog_manager: DialogManager,
) -> bool:
@@ -32,7 +32,7 @@ def __call__(
def new_when_field(fieldname: str) -> Predicate:
def when_field(
- data: Dict, widget: "Whenable", manager: DialogManager,
+ data: dict, widget: "Whenable", manager: DialogManager,
) -> bool:
return bool(data.get(fieldname))
@@ -41,14 +41,14 @@ def when_field(
def new_when_magic(f: MagicFilter) -> Predicate:
def when_magic(
- data: Dict, widget: "Whenable", manager: DialogManager,
+ data: dict, widget: "Whenable", manager: DialogManager,
) -> bool:
return f.resolve(data)
return when_magic
-def true_condition(data: Dict, widget: "Whenable", manager: DialogManager):
+def true_condition(data: dict, widget: "Whenable", manager: DialogManager):
return True
@@ -64,5 +64,5 @@ def __init__(self, when: WhenCondition = None):
else:
self.condition = when
- def is_(self, data: Dict, manager: DialogManager):
+ def is_(self, data: dict, manager: DialogManager):
return self.condition(data, self, manager)
diff --git a/src/aiogram_dialog/widgets/data/data_context.py b/src/aiogram_dialog/widgets/data/data_context.py
index 4798b7ca..c3cbd941 100644
--- a/src/aiogram_dialog/widgets/data/data_context.py
+++ b/src/aiogram_dialog/widgets/data/data_context.py
@@ -1,12 +1,10 @@
-from typing import Dict, List
-
from aiogram_dialog.api.internal.widgets import DataGetter
from aiogram_dialog.api.protocols import DialogManager
class CompositeGetter:
def __init__(self, *getters: DataGetter):
- self.getters: List[DataGetter] = list(getters)
+ self.getters: list[DataGetter] = list(getters)
async def __call__(self, **kwargs):
data = {}
@@ -16,7 +14,7 @@ async def __call__(self, **kwargs):
class StaticGetter:
- def __init__(self, data: Dict):
+ def __init__(self, data: dict):
self.data = data
async def __call__(self, **kwargs):
diff --git a/src/aiogram_dialog/widgets/input/base.py b/src/aiogram_dialog/widgets/input/base.py
index 32d3d143..ed893835 100644
--- a/src/aiogram_dialog/widgets/input/base.py
+++ b/src/aiogram_dialog/widgets/input/base.py
@@ -1,5 +1,6 @@
from abc import abstractmethod
-from typing import Any, Awaitable, Callable, Optional, Sequence, Union
+from typing import Any, Optional, Union
+from collections.abc import Awaitable, Callable, Sequence
from aiogram import F
from aiogram.dispatcher.event.handler import FilterObject
@@ -44,9 +45,8 @@ def __init__(
if isinstance(content_types, str):
if content_types != ContentType.ANY:
filters.append(FilterObject(F.content_type == content_types))
- else:
- if ContentType.ANY not in content_types:
- filters.append(FilterObject(F.content_type.in_(content_types)))
+ elif ContentType.ANY not in content_types:
+ filters.append(FilterObject(F.content_type.in_(content_types)))
if filter is not None:
filters.append(FilterObject(filter))
self.filters = filters
diff --git a/src/aiogram_dialog/widgets/input/combined.py b/src/aiogram_dialog/widgets/input/combined.py
index 9b37f3a8..c9194624 100644
--- a/src/aiogram_dialog/widgets/input/combined.py
+++ b/src/aiogram_dialog/widgets/input/combined.py
@@ -1,4 +1,5 @@
-from typing import Any, Callable, Optional
+from typing import Any, Optional
+from collections.abc import Callable
from aiogram.dispatcher.event.handler import FilterObject
from aiogram.types import Message
diff --git a/src/aiogram_dialog/widgets/input/text.py b/src/aiogram_dialog/widgets/input/text.py
index 0d1f0761..cd87b3e6 100644
--- a/src/aiogram_dialog/widgets/input/text.py
+++ b/src/aiogram_dialog/widgets/input/text.py
@@ -2,8 +2,14 @@
from abc import abstractmethod
from typing import (
- Any, Callable, Generic, Optional, Protocol, TypeVar, Union,
+ Any,
+ Generic,
+ Optional,
+ Protocol,
+ TypeVar,
+ Union,
)
+from collections.abc import Callable
from aiogram.dispatcher.event.handler import FilterObject
from aiogram.types import ContentType, Message
diff --git a/src/aiogram_dialog/widgets/kbd/button.py b/src/aiogram_dialog/widgets/kbd/button.py
index 8329e5d2..37e5355a 100644
--- a/src/aiogram_dialog/widgets/kbd/button.py
+++ b/src/aiogram_dialog/widgets/kbd/button.py
@@ -1,4 +1,5 @@
-from typing import Awaitable, Callable, Dict, List, Optional, Union
+from typing import Optional, Union
+from collections.abc import Awaitable, Callable
from aiogram.types import CallbackQuery, InlineKeyboardButton, WebAppInfo
@@ -38,7 +39,7 @@ async def _process_own_callback(
async def _render_keyboard(
self,
- data: Dict,
+ data: dict,
manager: DialogManager,
) -> RawKeyboard:
return [
@@ -65,7 +66,7 @@ def __init__(
async def _render_keyboard(
self,
- data: Dict,
+ data: dict,
manager: DialogManager,
) -> RawKeyboard:
return [
@@ -80,8 +81,8 @@ async def _render_keyboard(
class WebApp(Url):
async def _render_keyboard(
- self, data: Dict, manager: DialogManager,
- ) -> List[List[InlineKeyboardButton]]:
+ self, data: dict, manager: DialogManager,
+ ) -> list[list[InlineKeyboardButton]]:
text = await self.text.render_text(data, manager)
web_app_url = await self.url.render_text(data, manager)
@@ -104,9 +105,9 @@ def __init__(
async def _render_keyboard(
self,
- data: Dict,
+ data: dict,
manager: DialogManager,
- ) -> List[List[InlineKeyboardButton]]:
+ ) -> list[list[InlineKeyboardButton]]:
return [
[
InlineKeyboardButton(
diff --git a/src/aiogram_dialog/widgets/kbd/calendar_kbd.py b/src/aiogram_dialog/widgets/kbd/calendar_kbd.py
index a886f347..2ee1b07a 100644
--- a/src/aiogram_dialog/widgets/kbd/calendar_kbd.py
+++ b/src/aiogram_dialog/widgets/kbd/calendar_kbd.py
@@ -1,10 +1,16 @@
from __future__ import annotations
+from collections.abc import Callable
from dataclasses import dataclass
from datetime import date, datetime, timedelta, timezone
from enum import Enum
from typing import (
- Any, Callable, Dict, List, Optional, Protocol, TypedDict, TypeVar, Union,
+ Any,
+ Optional,
+ Protocol,
+ TypedDict,
+ TypeVar,
+ Union,
)
from aiogram.types import CallbackQuery, InlineKeyboardButton
@@ -66,8 +72,7 @@ class CalendarScope(Enum):
def raw_from_date(d: date) -> int:
diff = d - EPOCH
- raw_date = int(diff.total_seconds())
- return raw_date
+ return int(diff.total_seconds())
def date_from_raw(raw_date: int) -> date:
@@ -161,9 +166,9 @@ async def render(
self,
config: CalendarConfig,
offset: date,
- data: Dict,
+ data: dict,
manager: DialogManager,
- ) -> List[List[InlineKeyboardButton]]:
+ ) -> list[list[InlineKeyboardButton]]:
"""
Render keyboard for current scope.
@@ -203,7 +208,7 @@ async def _render_date_button(
self,
selected_date: date,
today: date,
- data: Dict,
+ data: dict,
manager: DialogManager,
) -> InlineKeyboardButton:
current_data = {
@@ -228,9 +233,9 @@ async def _render_days(
self,
config: CalendarConfig,
offset: date,
- data: Dict,
+ data: dict,
manager: DialogManager,
- ) -> List[List[InlineKeyboardButton]]:
+ ) -> list[list[InlineKeyboardButton]]:
keyboard = []
# align beginning
start_date = offset.replace(day=1) # month beginning
@@ -264,9 +269,9 @@ async def _render_days(
async def _render_week_header(
self,
config: CalendarConfig,
- data: Dict,
+ data: dict,
manager: DialogManager,
- ) -> List[InlineKeyboardButton]:
+ ) -> list[InlineKeyboardButton]:
week_range = range(config.firstweekday, config.firstweekday + 7)
header = []
for week_day in week_range:
@@ -286,9 +291,9 @@ async def _render_pager(
self,
config: CalendarConfig,
offset: date,
- data: Dict,
+ data: dict,
manager: DialogManager,
- ) -> List[InlineKeyboardButton]:
+ ) -> list[InlineKeyboardButton]:
curr_month = offset.month
next_month = (curr_month % 12) + 1
prev_month = (curr_month - 2) % 12 + 1
@@ -347,9 +352,9 @@ async def _render_header(
self,
config: CalendarConfig,
offset: date,
- data: Dict,
+ data: dict,
manager: DialogManager,
- ) -> List[InlineKeyboardButton]:
+ ) -> list[InlineKeyboardButton]:
data = {
"date": offset,
"data": data,
@@ -363,9 +368,9 @@ async def render(
self,
config: CalendarConfig,
offset: date,
- data: Dict,
+ data: dict,
manager: DialogManager,
- ) -> List[List[InlineKeyboardButton]]:
+ ) -> list[list[InlineKeyboardButton]]:
return [
await self._render_header(config, offset, data, manager),
await self._render_week_header(config, data, manager),
@@ -397,9 +402,9 @@ async def _render_pager(
self,
config: CalendarConfig,
offset: date,
- data: Dict,
+ data: dict,
manager: DialogManager,
- ) -> List[InlineKeyboardButton]:
+ ) -> list[InlineKeyboardButton]:
curr_year = offset.year
next_year = curr_year + 1
prev_year = curr_year - 1
@@ -467,7 +472,7 @@ async def _render_month_button(
self,
month: int,
this_month: int,
- data: Dict,
+ data: dict,
offset: date,
config: CalendarConfig,
manager: DialogManager,
@@ -498,9 +503,9 @@ async def _render_months(
self,
config: CalendarConfig,
offset: date,
- data: Dict,
+ data: dict,
manager: DialogManager,
- ) -> List[List[InlineKeyboardButton]]:
+ ) -> list[list[InlineKeyboardButton]]:
keyboard = []
today = get_today(config.timezone)
if offset.year == today.year:
@@ -519,7 +524,7 @@ async def _render_months(
async def _render_header(
self, config, offset, data, manager,
- ) -> List[InlineKeyboardButton]:
+ ) -> list[InlineKeyboardButton]:
data = {
"date": offset,
"data": data,
@@ -533,9 +538,9 @@ async def render(
self,
config: CalendarConfig,
offset: date,
- data: Dict,
+ data: dict,
manager: DialogManager,
- ) -> List[List[InlineKeyboardButton]]:
+ ) -> list[list[InlineKeyboardButton]]:
return [
await self._render_header(config, offset, data, manager),
*await self._render_months(config, offset, data, manager),
@@ -562,9 +567,9 @@ async def _render_pager(
self,
config: CalendarConfig,
offset: date,
- data: Dict,
+ data: dict,
manager: DialogManager,
- ) -> List[InlineKeyboardButton]:
+ ) -> list[InlineKeyboardButton]:
curr_year = offset.year
next_year = curr_year + config.years_per_page
prev_year = curr_year - config.years_per_page
@@ -619,7 +624,7 @@ async def _render_year_button(
self,
year: int,
this_year: int,
- data: Dict,
+ data: dict,
config: CalendarConfig,
manager: DialogManager,
) -> InlineKeyboardButton:
@@ -648,9 +653,9 @@ async def _render_years(
self,
config: CalendarConfig,
offset: date,
- data: Dict,
+ data: dict,
manager: DialogManager,
- ) -> List[List[InlineKeyboardButton]]:
+ ) -> list[list[InlineKeyboardButton]]:
keyboard = []
this_year = get_today(config.timezone).year
years_columns = config.years_columns
@@ -670,9 +675,9 @@ async def render(
self,
config: CalendarConfig,
offset: date,
- data: Dict,
+ data: dict,
manager: DialogManager,
- ) -> List[List[InlineKeyboardButton]]:
+ ) -> list[list[InlineKeyboardButton]]:
return [
*await self._render_years(config, offset, data, manager),
await self._render_pager(config, offset, data, manager),
@@ -718,7 +723,7 @@ def __init__(
CALLBACK_SCOPE_YEARS: self._handle_scope_years,
}
- def _init_views(self) -> Dict[CalendarScope, CalendarScopeView]:
+ def _init_views(self) -> dict[CalendarScope, CalendarScopeView]:
"""
Calendar scopes view initializer.
@@ -734,7 +739,7 @@ def _init_views(self) -> Dict[CalendarScope, CalendarScopeView]:
async def _get_user_config(
self,
- data: Dict,
+ data: dict,
manager: DialogManager,
) -> CalendarUserConfig:
"""
@@ -790,7 +795,7 @@ def set_scope(self, new_scope: CalendarScope,
data = self.get_widget_data(manager, {})
data["current_scope"] = new_scope.value
- def managed(self, manager: DialogManager) -> "ManagedCalendar":
+ def managed(self, manager: DialogManager) -> ManagedCalendar:
return ManagedCalendar(self, manager)
async def _handle_scope_months(
diff --git a/src/aiogram_dialog/widgets/kbd/checkbox.py b/src/aiogram_dialog/widgets/kbd/checkbox.py
index 634f8e15..7b0c21c1 100644
--- a/src/aiogram_dialog/widgets/kbd/checkbox.py
+++ b/src/aiogram_dialog/widgets/kbd/checkbox.py
@@ -1,5 +1,6 @@
from abc import ABC, abstractmethod
-from typing import Awaitable, Callable, Dict, Optional, Union
+from typing import Optional, Union
+from collections.abc import Awaitable, Callable
from aiogram.types import CallbackQuery, InlineKeyboardButton
@@ -41,7 +42,7 @@ def __init__(
self.on_state_changed = ensure_event_processor(on_state_changed)
async def _render_keyboard(
- self, data: Dict, manager: DialogManager,
+ self, data: dict, manager: DialogManager,
) -> RawKeyboard:
checked = int(self.is_checked(manager))
# store current checked status in callback data
@@ -70,7 +71,7 @@ async def _process_item_callback(
return True
def _is_text_checked(
- self, data: Dict, case: Case, manager: DialogManager,
+ self, data: dict, case: Case, manager: DialogManager,
) -> bool:
del data # unused
del case # unused
diff --git a/src/aiogram_dialog/widgets/kbd/counter.py b/src/aiogram_dialog/widgets/kbd/counter.py
index 35f914c7..a034c1ee 100644
--- a/src/aiogram_dialog/widgets/kbd/counter.py
+++ b/src/aiogram_dialog/widgets/kbd/counter.py
@@ -1,5 +1,5 @@
from abc import abstractmethod
-from typing import Dict, Optional, Protocol, Union
+from typing import Optional, Protocol, Union
from aiogram.types import CallbackQuery, InlineKeyboardButton
@@ -104,7 +104,7 @@ async def set_value(self, manager: DialogManager,
async def _render_keyboard(
self,
- data: Dict,
+ data: dict,
manager: DialogManager,
) -> RawKeyboard:
row = []
diff --git a/src/aiogram_dialog/widgets/kbd/group.py b/src/aiogram_dialog/widgets/kbd/group.py
index c8d5ec23..02d9e6b8 100644
--- a/src/aiogram_dialog/widgets/kbd/group.py
+++ b/src/aiogram_dialog/widgets/kbd/group.py
@@ -1,5 +1,6 @@
from itertools import chain
-from typing import Dict, Iterable, List, Optional
+from typing import Optional
+from collections.abc import Iterable
from aiogram.types import CallbackQuery, InlineKeyboardButton
@@ -33,7 +34,7 @@ def find(self, widget_id):
async def _render_keyboard(
self,
- data: Dict,
+ data: dict,
manager: DialogManager,
) -> RawKeyboard:
kbd: RawKeyboard = []
@@ -54,7 +55,7 @@ def _wrap_kbd(
kbd: Iterable[InlineKeyboardButton],
) -> RawKeyboard:
res: RawKeyboard = []
- row: List[ButtonVariant] = []
+ row: list[ButtonVariant] = []
for b in kbd:
row.append(b)
if len(row) >= self.width:
diff --git a/src/aiogram_dialog/widgets/kbd/list_group.py b/src/aiogram_dialog/widgets/kbd/list_group.py
index d137d02d..499e1ce1 100644
--- a/src/aiogram_dialog/widgets/kbd/list_group.py
+++ b/src/aiogram_dialog/widgets/kbd/list_group.py
@@ -1,4 +1,5 @@
-from typing import Any, Callable, Dict, Optional, Union
+from typing import Any, Optional, Union
+from collections.abc import Callable
from aiogram.types import CallbackQuery
@@ -9,7 +10,10 @@
from aiogram_dialog.manager.sub_manager import SubManager
from aiogram_dialog.widgets.common import ManagedWidget, WhenCondition
from .base import Keyboard
-from ..common.items import get_items_getter, ItemsGetterVariant
+from aiogram_dialog.widgets.common.items import (
+ get_items_getter,
+ ItemsGetterVariant,
+)
ItemIdGetter = Callable[[Any], Union[str, int]]
@@ -29,7 +33,7 @@ def __init__(
self.items_getter = get_items_getter(items)
async def _render_keyboard(
- self, data: Dict, manager: DialogManager,
+ self, data: dict, manager: DialogManager,
) -> RawKeyboard:
kbd: RawKeyboard = []
for pos, item in enumerate(self.items_getter(data)):
@@ -40,7 +44,7 @@ async def _render_item(
self,
pos: int,
item: Any,
- data: Dict,
+ data: dict,
manager: DialogManager,
) -> RawKeyboard:
kbd: RawKeyboard = []
diff --git a/src/aiogram_dialog/widgets/kbd/pager.py b/src/aiogram_dialog/widgets/kbd/pager.py
index 7d0b7ffa..e4958160 100644
--- a/src/aiogram_dialog/widgets/kbd/pager.py
+++ b/src/aiogram_dialog/widgets/kbd/pager.py
@@ -1,6 +1,6 @@
from abc import ABC
from enum import Enum
-from typing import Dict, TypedDict, Union
+from typing import TypedDict, Union
from aiogram.types import CallbackQuery, InlineKeyboardButton
@@ -20,7 +20,7 @@ class PageDirection(Enum):
class PagerData(TypedDict):
- data: Dict
+ data: dict
current_page: int
current_page1: int
pages: int
@@ -107,7 +107,7 @@ async def _get_target_page(
return min(last_page, current_page)
async def _prepare_data(
- self, data: Dict,
+ self, data: dict,
target_page: int,
current_page: int, pages: int,
) -> PagerPageData:
@@ -122,7 +122,7 @@ async def _prepare_data(
}
async def render_keyboard(
- self, data: Dict, manager: DialogManager,
+ self, data: dict, manager: DialogManager,
) -> RawKeyboard:
scroll = self._find_scroll(manager)
pages = await scroll.get_page_count(data)
@@ -229,7 +229,7 @@ def __init__(
self.current_page_text = current_page_text
async def _prepare_data(
- self, data: Dict,
+ self, data: dict,
current_page: int, pages: int,
) -> PagerData:
return {
@@ -240,7 +240,7 @@ async def _prepare_data(
}
async def _prepare_page_data(
- self, data: Dict, target_page: int,
+ self, data: dict, target_page: int,
) -> PagerData:
data = data.copy()
data["target_page"] = target_page
@@ -248,7 +248,7 @@ async def _prepare_page_data(
return data
async def render_keyboard(
- self, data: Dict, manager: DialogManager,
+ self, data: dict, manager: DialogManager,
) -> RawKeyboard:
scroll = self._find_scroll(manager)
pages = await scroll.get_page_count(data)
diff --git a/src/aiogram_dialog/widgets/kbd/request.py b/src/aiogram_dialog/widgets/kbd/request.py
index 026086c6..6dc9576e 100644
--- a/src/aiogram_dialog/widgets/kbd/request.py
+++ b/src/aiogram_dialog/widgets/kbd/request.py
@@ -1,4 +1,5 @@
-from typing import Callable, Dict, Union
+from typing import Union
+from collections.abc import Callable
from aiogram.types import KeyboardButton
@@ -19,7 +20,7 @@ def __init__(
async def _render_keyboard(
self,
- data: Dict,
+ data: dict,
manager: DialogManager,
) -> RawKeyboard:
return [
@@ -43,7 +44,7 @@ def __init__(
async def _render_keyboard(
self,
- data: Dict,
+ data: dict,
manager: DialogManager,
) -> RawKeyboard:
return [
diff --git a/src/aiogram_dialog/widgets/kbd/scrolling_group.py b/src/aiogram_dialog/widgets/kbd/scrolling_group.py
index 4bc01ad7..015d6165 100644
--- a/src/aiogram_dialog/widgets/kbd/scrolling_group.py
+++ b/src/aiogram_dialog/widgets/kbd/scrolling_group.py
@@ -1,4 +1,4 @@
-from typing import Dict, List, Optional
+from typing import Optional
from aiogram.types import CallbackQuery, InlineKeyboardButton
@@ -37,7 +37,7 @@ def _get_page_count(
async def _render_contents(
self,
- data: Dict,
+ data: dict,
manager: DialogManager,
) -> RawKeyboard:
return await super()._render_keyboard(data, manager)
@@ -84,8 +84,8 @@ async def _render_pager(
async def _render_page(
self,
page: int,
- keyboard: List[List[InlineKeyboardButton]],
- ) -> List[List[InlineKeyboardButton]]:
+ keyboard: list[list[InlineKeyboardButton]],
+ ) -> list[list[InlineKeyboardButton]]:
pages = self._get_page_count(keyboard)
last_page = pages - 1
current_page = min(last_page, page)
@@ -95,7 +95,7 @@ async def _render_page(
async def _render_keyboard(
self,
- data: Dict,
+ data: dict,
manager: DialogManager,
) -> RawKeyboard:
keyboard = await self._render_contents(data, manager)
@@ -119,6 +119,6 @@ async def _process_item_callback(
await self.set_page(callback, int(data), manager)
return True
- async def get_page_count(self, data: Dict, manager: DialogManager) -> int:
+ async def get_page_count(self, data: dict, manager: DialogManager) -> int:
keyboard = await self._render_contents(data, manager)
return self._get_page_count(keyboard=keyboard)
diff --git a/src/aiogram_dialog/widgets/kbd/select.py b/src/aiogram_dialog/widgets/kbd/select.py
index b3959760..5596c7a8 100644
--- a/src/aiogram_dialog/widgets/kbd/select.py
+++ b/src/aiogram_dialog/widgets/kbd/select.py
@@ -1,10 +1,8 @@
from abc import ABC, abstractmethod
+from collections.abc import Callable
from typing import (
Any,
- Callable,
- Dict,
Generic,
- List,
Optional,
Protocol,
TypeVar,
@@ -17,13 +15,16 @@
from aiogram_dialog.api.internal import RawKeyboard
from aiogram_dialog.api.protocols import DialogManager, DialogProtocol
from aiogram_dialog.widgets.common import ManagedWidget, WhenCondition
+from aiogram_dialog.widgets.common.items import (
+ get_items_getter,
+ ItemsGetterVariant,
+)
from aiogram_dialog.widgets.text import Case, Text
from aiogram_dialog.widgets.widget_event import (
ensure_event_processor,
WidgetEventProcessor,
)
from .base import Keyboard
-from ..common.items import get_items_getter, ItemsGetterVariant
T = TypeVar("T")
ManagedT = TypeVar("ManagedT")
@@ -79,7 +80,7 @@ def __init__(
async def _render_keyboard(
self,
- data: Dict,
+ data: dict,
manager: DialogManager,
) -> RawKeyboard:
return [
@@ -90,7 +91,7 @@ async def _render_keyboard(
]
async def _render_button(
- self, pos: int, item: Any, target_item: Any, data: Dict,
+ self, pos: int, item: Any, target_item: Any, data: dict,
manager: DialogManager,
) -> InlineKeyboardButton:
"""
@@ -167,7 +168,7 @@ async def _process_on_state_changed(
@abstractmethod
def _is_text_checked(
- self, data: Dict, case: Case, manager: DialogManager,
+ self, data: dict, case: Case, manager: DialogManager,
) -> bool:
raise NotImplementedError
@@ -272,7 +273,7 @@ def _preview_checked_id(
return self.get_widget_data(manager, item_id)
def _is_text_checked(
- self, data: Dict, case: Case, manager: DialogManager,
+ self, data: dict, case: Case, manager: DialogManager,
) -> bool:
item_id = self.item_id_getter(data["item"])
if manager.is_preview():
@@ -344,7 +345,7 @@ def __init__(
self.max_selected = max_selected
def _is_text_checked(
- self, data: Dict, case: Case, manager: DialogManager,
+ self, data: dict, case: Case, manager: DialogManager,
) -> bool:
item_id = str(self.item_id_getter(data["item"]))
if manager.is_preview():
@@ -360,10 +361,10 @@ def is_checked(
data = self._get_checked(manager)
return str(item_id) in data
- def _get_checked(self, manager: DialogManager) -> List[str]:
+ def _get_checked(self, manager: DialogManager) -> list[str]:
return self.get_widget_data(manager, [])
- def get_checked(self, manager: DialogManager) -> List[T]:
+ def get_checked(self, manager: DialogManager) -> list[T]:
return [self.type_factory(item) for item in self._get_checked(manager)]
async def reset_checked(
@@ -379,18 +380,15 @@ async def set_checked(
manager: DialogManager,
) -> None:
item_id_str = str(item_id)
- data: List = self._get_checked(manager)
+ data: list = self._get_checked(manager)
changed = False
if item_id_str in data:
- if not checked:
- if len(data) > self.min_selected:
- data.remove(item_id_str)
- changed = True
- else:
- if checked:
- if self.max_selected == 0 or self.max_selected > len(data):
- data.append(item_id_str)
- changed = True
+ if not checked and len(data) > self.min_selected:
+ data.remove(item_id_str)
+ changed = True
+ elif checked and self.max_selected == 0 or self.max_selected > len(data):
+ data.append(item_id_str)
+ changed = True
if changed:
self.set_widget_data(manager, data)
await self._process_on_state_changed(event, item_id_str, manager)
@@ -415,7 +413,7 @@ def is_checked(self, item_id: T) -> bool:
"""Get if an item identified by ``item_id`` is checked."""
return self.widget.is_checked(item_id, self.manager)
- def get_checked(self) -> List[T]:
+ def get_checked(self) -> list[T]:
"""Get a list of checked items ids."""
return self.widget.get_checked(self.manager)
@@ -459,7 +457,7 @@ def __init__(
async def _render_keyboard(
self,
- data: Dict,
+ data: dict,
manager: DialogManager,
) -> RawKeyboard:
items_it = iter(self.items_getter(data))
diff --git a/src/aiogram_dialog/widgets/kbd/stub_scroll.py b/src/aiogram_dialog/widgets/kbd/stub_scroll.py
index 3e71625e..5d3b5178 100644
--- a/src/aiogram_dialog/widgets/kbd/stub_scroll.py
+++ b/src/aiogram_dialog/widgets/kbd/stub_scroll.py
@@ -1,18 +1,22 @@
-from typing import Callable, Dict, Union
+from typing import Union
+from collections.abc import Callable
from magic_filter import MagicFilter
from aiogram_dialog.api.internal import RawKeyboard
from aiogram_dialog.api.protocols import DialogManager
from .base import Keyboard
-from ..common.scroll import BaseScroll, OnPageChangedVariants
+from aiogram_dialog.widgets.common.scroll import (
+ BaseScroll,
+ OnPageChangedVariants,
+)
-PagesGetter = Callable[[Dict, "StubScroll", DialogManager], int]
+PagesGetter = Callable[[dict, "StubScroll", DialogManager], int]
def new_pages_field(fieldname: str) -> PagesGetter:
def pages_field(
- data: Dict, widget: "StubScroll", manager: DialogManager,
+ data: dict, widget: "StubScroll", manager: DialogManager,
) -> int:
return data.get(fieldname)
@@ -21,7 +25,7 @@ def pages_field(
def new_pages_magic(f: MagicFilter) -> PagesGetter:
def pages_magic(
- data: Dict, widget: "StubScroll", manager: DialogManager,
+ data: dict, widget: "StubScroll", manager: DialogManager,
) -> int:
return f.resolve(data)
@@ -30,7 +34,7 @@ def pages_magic(
def new_pages_fixed(pages: int) -> PagesGetter:
def pages_fixed(
- data: Dict, widget: "StubScroll", manager: DialogManager,
+ data: dict, widget: "StubScroll", manager: DialogManager,
) -> int:
return pages
@@ -55,10 +59,10 @@ def __init__(
async def _render_keyboard(
self,
- data: Dict,
+ data: dict,
manager: DialogManager,
) -> RawKeyboard:
return [[]]
- async def get_page_count(self, data: Dict, manager: DialogManager) -> int:
+ async def get_page_count(self, data: dict, manager: DialogManager) -> int:
return self._pages(data, self, manager)
diff --git a/src/aiogram_dialog/widgets/media/dynamic.py b/src/aiogram_dialog/widgets/media/dynamic.py
index c4920739..3b602f7f 100644
--- a/src/aiogram_dialog/widgets/media/dynamic.py
+++ b/src/aiogram_dialog/widgets/media/dynamic.py
@@ -6,7 +6,8 @@
"""
from operator import itemgetter
-from typing import Callable, Optional, Union
+from typing import Optional, Union
+from collections.abc import Callable
from aiogram_dialog import DialogManager
from aiogram_dialog.api.entities import MediaAttachment
diff --git a/src/aiogram_dialog/widgets/media/scroll.py b/src/aiogram_dialog/widgets/media/scroll.py
index 9157d693..34bee7cb 100644
--- a/src/aiogram_dialog/widgets/media/scroll.py
+++ b/src/aiogram_dialog/widgets/media/scroll.py
@@ -1,4 +1,4 @@
-from typing import Dict, Optional
+from typing import Optional
from aiogram_dialog.api.entities import MediaAttachment
from aiogram_dialog.api.protocols import DialogManager
@@ -6,7 +6,10 @@
BaseScroll, OnPageChangedVariants, WhenCondition,
)
from .base import Media
-from ..common.items import get_items_getter, ItemsGetterVariant
+from aiogram_dialog.widgets.common.items import (
+ get_items_getter,
+ ItemsGetterVariant,
+)
class MediaScroll(Media, BaseScroll):
@@ -44,6 +47,6 @@ async def _render_media(
manager,
)
- async def get_page_count(self, data: Dict, manager: DialogManager) -> int:
+ async def get_page_count(self, data: dict, manager: DialogManager) -> int:
items = self.items_getter(data)
return len(items)
diff --git a/src/aiogram_dialog/widgets/text/base.py b/src/aiogram_dialog/widgets/text/base.py
index 4309c406..726f38da 100644
--- a/src/aiogram_dialog/widgets/text/base.py
+++ b/src/aiogram_dialog/widgets/text/base.py
@@ -1,5 +1,5 @@
from abc import abstractmethod
-from typing import Dict, Optional, Union
+from typing import Optional, Union
from aiogram_dialog.api.internal import TextWidget
from aiogram_dialog.api.protocols import DialogManager
@@ -13,7 +13,7 @@ def __init__(self, when: WhenCondition = None):
super().__init__(when=when)
async def render_text(
- self, data: Dict, manager: DialogManager,
+ self, data: dict, manager: DialogManager,
) -> str:
"""
Create text.
@@ -69,7 +69,7 @@ def __init__(self, text: str, when: WhenCondition = None):
self.text = text
async def _render_text(
- self, data: Dict, manager: DialogManager,
+ self, data: dict, manager: DialogManager,
) -> str:
return self.text
@@ -81,7 +81,7 @@ def __init__(self, *texts: Text, sep="\n", when: WhenCondition = None):
self.sep = sep
async def _render_text(
- self, data: Dict, manager: DialogManager,
+ self, data: dict, manager: DialogManager,
) -> str:
texts = [await t.render_text(data, manager) for t in self.texts]
return self.sep.join(filter(None, texts))
@@ -123,7 +123,7 @@ def __init__(self, *texts: Text):
self.texts = texts
async def _render_text(
- self, data: Dict, manager: DialogManager,
+ self, data: dict, manager: DialogManager,
) -> str:
for text in self.texts:
res = await text.render_text(data, manager)
diff --git a/src/aiogram_dialog/widgets/text/format.py b/src/aiogram_dialog/widgets/text/format.py
index d6caedbe..89e564ce 100644
--- a/src/aiogram_dialog/widgets/text/format.py
+++ b/src/aiogram_dialog/widgets/text/format.py
@@ -1,5 +1,3 @@
-from typing import Dict
-
from aiogram_dialog.api.protocols import DialogManager
from aiogram_dialog.widgets.common import WhenCondition
from .base import Text
@@ -34,7 +32,7 @@ def __init__(self, text: str, when: WhenCondition = None):
self.text = text
async def _render_text(
- self, data: Dict, manager: DialogManager,
+ self, data: dict, manager: DialogManager,
) -> str:
if manager.is_preview():
return self.text.format_map(_FormatDataStub(data=data))
diff --git a/src/aiogram_dialog/widgets/text/jinja.py b/src/aiogram_dialog/widgets/text/jinja.py
index 65a2348f..abe38781 100644
--- a/src/aiogram_dialog/widgets/text/jinja.py
+++ b/src/aiogram_dialog/widgets/text/jinja.py
@@ -1,14 +1,10 @@
import warnings
from typing import (
Any,
- Callable,
- Dict,
- Iterable,
- Mapping,
Optional,
- Tuple,
Union,
)
+from collections.abc import Callable, Iterable, Mapping
from aiogram import Bot, Dispatcher
from jinja2 import BaseLoader, Environment
@@ -20,7 +16,7 @@
JINJA_ENV_FIELD = "DialogsJinjaEnvironment"
Filter = Callable[..., str]
-Filters = Union[Iterable[Tuple[str, Filter]], Mapping[str, Filter]]
+Filters = Union[Iterable[tuple[str, Filter]], Mapping[str, Filter]]
class Jinja(Text):
@@ -29,7 +25,7 @@ def __init__(self, text: str, when: WhenCondition = None):
self.template_text = text
async def _render_text(
- self, data: Dict, manager: DialogManager,
+ self, data: dict, manager: DialogManager,
) -> str:
if JINJA_ENV_FIELD in manager.middleware_data:
env = manager.middleware_data[JINJA_ENV_FIELD]
@@ -58,7 +54,7 @@ def _create_env(
kwargs.setdefault("trim_blocks", True)
if "loader" not in kwargs:
kwargs["loader"] = StubLoader()
- env = Environment(*args, **kwargs)
+ env = Environment(*args, **kwargs) # noqa: S701
if filters is not None:
env.filters.update(filters)
return env
diff --git a/src/aiogram_dialog/widgets/text/list.py b/src/aiogram_dialog/widgets/text/list.py
index b64a52d9..5dd7458e 100644
--- a/src/aiogram_dialog/widgets/text/list.py
+++ b/src/aiogram_dialog/widgets/text/list.py
@@ -1,11 +1,15 @@
-from typing import Any, Dict, Optional, Sequence
+from typing import Any, Optional
+from collections.abc import Sequence
from aiogram_dialog.api.protocols import DialogManager
from aiogram_dialog.widgets.common import (
BaseScroll, OnPageChangedVariants, WhenCondition,
)
from .base import Text
-from ..common.items import get_items_getter, ItemsGetterVariant
+from aiogram_dialog.widgets.common.items import (
+ get_items_getter,
+ ItemsGetterVariant,
+)
class List(Text, BaseScroll):
@@ -27,7 +31,7 @@ def __init__(
self.page_size = page_size
async def _render_text(
- self, data: Dict, manager: DialogManager,
+ self, data: dict, manager: DialogManager,
) -> str:
items = self.items_getter(data)
pages = self._get_page_count(items)
@@ -57,7 +61,7 @@ async def _render_text(
]
return self.sep.join(filter(None, texts))
- async def get_page_count(self, data: Dict, manager: DialogManager) -> int:
+ async def get_page_count(self, data: dict, manager: DialogManager) -> int:
items = self.items_getter(data)
return self._get_page_count(items)
diff --git a/src/aiogram_dialog/widgets/text/multi.py b/src/aiogram_dialog/widgets/text/multi.py
index 221e6be4..d5efc5ee 100644
--- a/src/aiogram_dialog/widgets/text/multi.py
+++ b/src/aiogram_dialog/widgets/text/multi.py
@@ -1,4 +1,5 @@
-from typing import Any, Callable, Dict, Hashable, Optional, Union
+from typing import Any, Optional, Union
+from collections.abc import Callable, Hashable
from magic_filter import MagicFilter
@@ -6,12 +7,12 @@
from aiogram_dialog.widgets.common import WhenCondition
from .base import Text
-Selector = Callable[[Dict, "Case", DialogManager], Hashable]
+Selector = Callable[[dict, "Case", DialogManager], Hashable]
def new_case_field(fieldname: str) -> Selector:
def case_field(
- data: Dict, widget: "Case", manager: DialogManager,
+ data: dict, widget: "Case", manager: DialogManager,
) -> Hashable:
return data.get(fieldname)
@@ -20,7 +21,7 @@ def case_field(
def new_magic_selector(f: MagicFilter) -> Selector:
def when_magic(
- data: Dict, widget: "Case", manager: DialogManager,
+ data: dict, widget: "Case", manager: DialogManager,
) -> bool:
return f.resolve(data)
@@ -30,7 +31,7 @@ def when_magic(
class Case(Text):
def __init__(
self,
- texts: Dict[Any, Text],
+ texts: dict[Any, Text],
selector: Union[str, Selector, MagicFilter],
when: WhenCondition = None,
):
diff --git a/src/aiogram_dialog/widgets/text/progress.py b/src/aiogram_dialog/widgets/text/progress.py
index 1b5245f7..cb20ff14 100644
--- a/src/aiogram_dialog/widgets/text/progress.py
+++ b/src/aiogram_dialog/widgets/text/progress.py
@@ -1,5 +1,3 @@
-from typing import Dict
-
from aiogram_dialog.api.protocols import DialogManager
from aiogram_dialog.widgets.common import WhenCondition
from .base import Text
@@ -21,7 +19,7 @@ def __init__(
self.empty = empty
async def _render_text(
- self, data: Dict, manager: DialogManager,
+ self, data: dict, manager: DialogManager,
) -> str:
if manager.is_preview():
percent = 15
diff --git a/src/aiogram_dialog/widgets/text/scrolling_text.py b/src/aiogram_dialog/widgets/text/scrolling_text.py
index df5376a9..206fe076 100644
--- a/src/aiogram_dialog/widgets/text/scrolling_text.py
+++ b/src/aiogram_dialog/widgets/text/scrolling_text.py
@@ -1,5 +1,3 @@
-from typing import Dict
-
from aiogram_dialog.api.protocols import DialogManager
from aiogram_dialog.widgets.common import (
BaseScroll, OnPageChangedVariants, WhenCondition,
@@ -29,7 +27,7 @@ def _get_page_count(
async def _render_contents(
self,
- data: Dict,
+ data: dict,
manager: DialogManager,
) -> str:
return await self.text.render_text(data, manager)
@@ -44,6 +42,6 @@ async def _render_text(self, data, manager: DialogManager) -> str:
return text[page_offset: page_offset + self.page_size]
- async def get_page_count(self, data: Dict, manager: DialogManager) -> int:
+ async def get_page_count(self, data: dict, manager: DialogManager) -> int:
text = await self._render_contents(data, manager)
return self._get_page_count(text)
diff --git a/src/aiogram_dialog/widgets/utils.py b/src/aiogram_dialog/widgets/utils.py
index 3deb8807..3ce7e994 100644
--- a/src/aiogram_dialog/widgets/utils.py
+++ b/src/aiogram_dialog/widgets/utils.py
@@ -1,4 +1,5 @@
-from typing import Callable, Dict, List, Sequence, Tuple, Union
+from typing import Union
+from collections.abc import Callable, Sequence
from aiogram_dialog.api.exceptions import InvalidWidgetType
from aiogram_dialog.api.internal import DataGetter
@@ -11,12 +12,12 @@
WidgetSrc = Union[str, Text, Keyboard, MessageHandlerFunc, Media, BaseInput]
-SingleGetterBase = Union[DataGetter, Dict]
+SingleGetterBase = Union[DataGetter, dict]
GetterVariant = Union[
None,
SingleGetterBase,
- List[SingleGetterBase],
- Tuple[SingleGetterBase, ...],
+ list[SingleGetterBase],
+ tuple[SingleGetterBase, ...],
]
@@ -71,7 +72,7 @@ def ensure_media(widget: Union[Media, Sequence[Media]]) -> Media:
def ensure_widgets(
widgets: Sequence[WidgetSrc],
-) -> Tuple[Text, Keyboard, Union[BaseInput, None], Media]:
+) -> tuple[Text, Keyboard, Union[BaseInput, None], Media]:
texts = []
keyboards = []
inputs = []
diff --git a/src/aiogram_dialog/widgets/widget_event.py b/src/aiogram_dialog/widgets/widget_event.py
index 42823b05..d15cafe9 100644
--- a/src/aiogram_dialog/widgets/widget_event.py
+++ b/src/aiogram_dialog/widgets/widget_event.py
@@ -1,5 +1,6 @@
from abc import abstractmethod
-from typing import Any, Callable, Union
+from typing import Any, Union
+from collections.abc import Callable
from aiogram_dialog.api.entities import ChatEvent
from aiogram_dialog.api.protocols import DialogManager
diff --git a/src/aiogram_dialog/window.py b/src/aiogram_dialog/window.py
index af02a0d2..d14078a6 100644
--- a/src/aiogram_dialog/window.py
+++ b/src/aiogram_dialog/window.py
@@ -1,5 +1,5 @@
from logging import getLogger
-from typing import Any, cast, Dict, List, Optional
+from typing import Any, cast, Optional
from aiogram.fsm.state import State
from aiogram.types import (
@@ -46,7 +46,7 @@ def __init__(
markup_factory: MarkupFactory = _DEFAULT_MARKUP_FACTORY,
parse_mode: Optional[str] = UNSET_PARSE_MODE,
disable_web_page_preview: Optional[bool] = UNSET_DISABLE_WEB_PAGE_PREVIEW, # noqa: E501
- preview_add_transitions: Optional[List[Keyboard]] = None,
+ preview_add_transitions: Optional[list[Keyboard]] = None,
preview_data: GetterVariant = None,
):
(
@@ -67,18 +67,18 @@ def __init__(
self.preview_add_transitions = preview_add_transitions
async def render_text(
- self, data: Dict, manager: DialogManager,
+ self, data: dict, manager: DialogManager,
) -> str:
return await self.text.render_text(data, manager)
async def render_media(
- self, data: Dict, manager: DialogManager,
+ self, data: dict, manager: DialogManager,
) -> Optional[MediaAttachment]:
if self.media:
return await self.media.render_media(data, manager)
async def render_kbd(
- self, data: Dict, manager: DialogManager,
+ self, data: dict, manager: DialogManager,
) -> MarkupVariant:
keyboard = await self.keyboard.render_keyboard(data, manager)
return await self.markup_factory.render_markup(
@@ -88,7 +88,7 @@ async def render_kbd(
async def load_data(
self, dialog: "DialogProtocol",
manager: DialogManager,
- ) -> Dict:
+ ) -> dict:
data = await dialog.load_data(manager)
data.update(await self.getter(**manager.middleware_data))
return data
@@ -153,9 +153,8 @@ def get_state(self) -> State:
def find(self, widget_id) -> Optional[Widget]:
for root in (self.text, self.keyboard, self.on_message, self.media):
- if root:
- if found := root.find(widget_id):
- return found
+ if root and (found := root.find(widget_id)):
+ return found
return None
def __repr__(self) -> str:
diff --git a/tests/test_click.py b/tests/test_click.py
index 3233dba9..0ec5d22f 100644
--- a/tests/test_click.py
+++ b/tests/test_click.py
@@ -1,4 +1,4 @@
-from typing import Any, Dict
+from typing import Any
from unittest.mock import Mock
import pytest
@@ -31,7 +31,7 @@ async def on_finish(event, button, manager: DialogManager) -> None:
await manager.done()
-async def second_getter(user_getter, **kwargs) -> Dict[str, Any]:
+async def second_getter(user_getter, **kwargs) -> dict[str, Any]:
return {
"user": user_getter(),
}
From a5b3734bfed1a2f9f7055b0db889d6fbfb82c35e Mon Sep 17 00:00:00 2001
From: chiri <2alivemafia@gmail.com>
Date: Wed, 6 Nov 2024 00:47:06 +0300
Subject: [PATCH 08/29] hotfix: add accidentally deleted requirements
---
requirements_dev.txt | 17 +++++++++++++++++
requirements_doc.txt | 4 ++++
2 files changed, 21 insertions(+)
create mode 100644 requirements_dev.txt
create mode 100644 requirements_doc.txt
diff --git a/requirements_dev.txt b/requirements_dev.txt
new file mode 100644
index 00000000..07c80a1e
--- /dev/null
+++ b/requirements_dev.txt
@@ -0,0 +1,17 @@
+vulture
+flake8==7.*
+flake8-blind-except
+flake8-bugbear
+flake8-builtins
+flake8-cognitive-complexity
+flake8-comprehensions
+flake8-docstrings
+flake8-eradicate
+flake8-import-order
+flake8-mutable
+flake8-polyfill
+flake8-print
+
+pytest
+pytest-asyncio
+pytest-repeat
\ No newline at end of file
diff --git a/requirements_doc.txt b/requirements_doc.txt
new file mode 100644
index 00000000..76386171
--- /dev/null
+++ b/requirements_doc.txt
@@ -0,0 +1,4 @@
+sphinx
+sphinx-autodocgen
+furo
+sphinx-copybutton
\ No newline at end of file
From 2667b20c8e0e1a7a2ada17cc54177dc21bc1ddb4 Mon Sep 17 00:00:00 2001
From: chiri <2alivemafia@gmail.com>
Date: Wed, 6 Nov 2024 00:57:30 +0300
Subject: [PATCH 09/29] fix for flake 8
---
src/aiogram_dialog/__init__.py | 17 ++++++--
src/aiogram_dialog/api/entities/__init__.py | 10 +++--
.../api/entities/new_message.py | 5 ++-
src/aiogram_dialog/api/entities/stack.py | 1 +
src/aiogram_dialog/api/internal/__init__.py | 16 ++++++--
src/aiogram_dialog/api/internal/manager.py | 3 +-
src/aiogram_dialog/api/internal/widgets.py | 14 +++++--
src/aiogram_dialog/api/internal/window.py | 1 +
src/aiogram_dialog/api/protocols/__init__.py | 5 ++-
src/aiogram_dialog/api/protocols/dialog.py | 5 ++-
src/aiogram_dialog/api/protocols/manager.py | 7 +++-
.../context/access_validator.py | 3 +-
.../context/intent_middleware.py | 26 +++++++++----
src/aiogram_dialog/context/storage.py | 9 ++++-
src/aiogram_dialog/dialog.py | 7 +++-
src/aiogram_dialog/manager/bg_manager.py | 9 +++--
src/aiogram_dialog/manager/manager.py | 39 ++++++++++++++-----
src/aiogram_dialog/manager/manager_factory.py | 7 +++-
.../manager/manager_middleware.py | 8 ++--
src/aiogram_dialog/manager/message_manager.py | 9 ++++-
src/aiogram_dialog/manager/sub_manager.py | 12 ++++--
src/aiogram_dialog/setup.py | 20 ++++++----
src/aiogram_dialog/test_tools/bot_client.py | 18 +++++++--
.../test_tools/memory_storage.py | 1 -
.../test_tools/mock_message_manager.py | 10 ++++-
src/aiogram_dialog/tools/preview.py | 2 +-
src/aiogram_dialog/utils.py | 4 +-
src/aiogram_dialog/widgets/common/__init__.py | 2 +-
src/aiogram_dialog/widgets/common/action.py | 1 +
src/aiogram_dialog/widgets/common/items.py | 2 +-
src/aiogram_dialog/widgets/common/scroll.py | 6 ++-
src/aiogram_dialog/widgets/input/base.py | 7 ++--
src/aiogram_dialog/widgets/input/combined.py | 6 ++-
src/aiogram_dialog/widgets/input/text.py | 5 ++-
src/aiogram_dialog/widgets/kbd/__init__.py | 5 ++-
src/aiogram_dialog/widgets/kbd/button.py | 5 ++-
.../widgets/kbd/calendar_kbd.py | 4 +-
src/aiogram_dialog/widgets/kbd/checkbox.py | 5 ++-
src/aiogram_dialog/widgets/kbd/counter.py | 2 +-
src/aiogram_dialog/widgets/kbd/group.py | 3 +-
src/aiogram_dialog/widgets/kbd/list_group.py | 10 +++--
src/aiogram_dialog/widgets/kbd/pager.py | 1 +
src/aiogram_dialog/widgets/kbd/request.py | 3 +-
.../widgets/kbd/scrolling_group.py | 5 ++-
src/aiogram_dialog/widgets/kbd/select.py | 5 ++-
src/aiogram_dialog/widgets/kbd/stub_scroll.py | 5 ++-
.../widgets/markup/force_reply.py | 4 +-
.../widgets/markup/inline_keyboard.py | 4 +-
.../widgets/markup/reply_keyboard.py | 4 +-
src/aiogram_dialog/widgets/media/dynamic.py | 2 +-
src/aiogram_dialog/widgets/media/scroll.py | 9 +++--
src/aiogram_dialog/widgets/media/static.py | 1 +
src/aiogram_dialog/widgets/text/base.py | 5 ++-
src/aiogram_dialog/widgets/text/format.py | 1 +
src/aiogram_dialog/widgets/text/jinja.py | 3 +-
src/aiogram_dialog/widgets/text/list.py | 11 ++++--
src/aiogram_dialog/widgets/text/multi.py | 3 +-
src/aiogram_dialog/widgets/text/progress.py | 1 +
.../widgets/text/scrolling_text.py | 5 ++-
src/aiogram_dialog/widgets/utils.py | 3 +-
src/aiogram_dialog/widgets/widget_event.py | 2 +-
src/aiogram_dialog/window.py | 9 +++--
62 files changed, 296 insertions(+), 121 deletions(-)
diff --git a/src/aiogram_dialog/__init__.py b/src/aiogram_dialog/__init__.py
index d6d649e5..474f5717 100644
--- a/src/aiogram_dialog/__init__.py
+++ b/src/aiogram_dialog/__init__.py
@@ -22,12 +22,21 @@
import importlib.metadata as _metadata
from .api.entities import (
- AccessSettings, ChatEvent, Data, DEFAULT_STACK_ID, GROUP_STACK_ID,
- LaunchMode, ShowMode, StartMode,
+ DEFAULT_STACK_ID,
+ GROUP_STACK_ID,
+ AccessSettings,
+ ChatEvent,
+ Data,
+ LaunchMode,
+ ShowMode,
+ StartMode,
)
from .api.protocols import (
- BaseDialogManager, BgManagerFactory, CancelEventProcessing,
- DialogManager, DialogProtocol,
+ BaseDialogManager,
+ BgManagerFactory,
+ CancelEventProcessing,
+ DialogManager,
+ DialogProtocol,
UnsetId,
)
from .dialog import Dialog
diff --git a/src/aiogram_dialog/api/entities/__init__.py b/src/aiogram_dialog/api/entities/__init__.py
index 38b04326..4626999a 100644
--- a/src/aiogram_dialog/api/entities/__init__.py
+++ b/src/aiogram_dialog/api/entities/__init__.py
@@ -12,13 +12,17 @@
from .access import AccessSettings
from .context import Context, Data
-from .events import ChatEvent, EVENT_CONTEXT_KEY, EventContext
+from .events import EVENT_CONTEXT_KEY, ChatEvent, EventContext
from .launch_mode import LaunchMode
from .media import MediaAttachment, MediaId
from .modes import ShowMode, StartMode
from .new_message import MarkupVariant, NewMessage, OldMessage, UnknownText
from .stack import DEFAULT_STACK_ID, GROUP_STACK_ID, Stack
from .update_event import (
- DIALOG_EVENT_NAME, DialogAction, DialogStartEvent, DialogSwitchEvent,
- DialogUpdate, DialogUpdateEvent,
+ DIALOG_EVENT_NAME,
+ DialogAction,
+ DialogStartEvent,
+ DialogSwitchEvent,
+ DialogUpdate,
+ DialogUpdateEvent,
)
diff --git a/src/aiogram_dialog/api/entities/new_message.py b/src/aiogram_dialog/api/entities/new_message.py
index a0f16221..062f794f 100644
--- a/src/aiogram_dialog/api/entities/new_message.py
+++ b/src/aiogram_dialog/api/entities/new_message.py
@@ -3,7 +3,10 @@
from typing import Optional, Union
from aiogram.types import (
- Chat, ForceReply, InlineKeyboardMarkup, ReplyKeyboardMarkup,
+ Chat,
+ ForceReply,
+ InlineKeyboardMarkup,
+ ReplyKeyboardMarkup,
ReplyKeyboardRemove,
)
diff --git a/src/aiogram_dialog/api/entities/stack.py b/src/aiogram_dialog/api/entities/stack.py
index 824830b1..3256d018 100644
--- a/src/aiogram_dialog/api/entities/stack.py
+++ b/src/aiogram_dialog/api/entities/stack.py
@@ -7,6 +7,7 @@
from aiogram.fsm.state import State
from aiogram_dialog.api.exceptions import DialogStackOverflow
+
from .access import AccessSettings
from .context import Context, Data
diff --git a/src/aiogram_dialog/api/internal/__init__.py b/src/aiogram_dialog/api/internal/__init__.py
index c3e86d15..62dcf102 100644
--- a/src/aiogram_dialog/api/internal/__init__.py
+++ b/src/aiogram_dialog/api/internal/__init__.py
@@ -13,10 +13,20 @@
DialogManagerFactory,
)
from .middleware import (
- CALLBACK_DATA_KEY, CONTEXT_KEY, EVENT_SIMULATED, STACK_KEY, STORAGE_KEY,
+ CALLBACK_DATA_KEY,
+ CONTEXT_KEY,
+ EVENT_SIMULATED,
+ STACK_KEY,
+ STORAGE_KEY,
)
from .widgets import (
- ButtonVariant, DataGetter, InputWidget, KeyboardWidget,
- MediaWidget, RawKeyboard, TextWidget, Widget,
+ ButtonVariant,
+ DataGetter,
+ InputWidget,
+ KeyboardWidget,
+ MediaWidget,
+ RawKeyboard,
+ TextWidget,
+ Widget,
)
from .window import WindowProtocol
diff --git a/src/aiogram_dialog/api/internal/manager.py b/src/aiogram_dialog/api/internal/manager.py
index 145743c2..f5ed9d6c 100644
--- a/src/aiogram_dialog/api/internal/manager.py
+++ b/src/aiogram_dialog/api/internal/manager.py
@@ -5,7 +5,8 @@
from aiogram_dialog.api.entities import ChatEvent
from aiogram_dialog.api.protocols import (
- DialogManager, DialogRegistryProtocol,
+ DialogManager,
+ DialogRegistryProtocol,
)
diff --git a/src/aiogram_dialog/api/internal/widgets.py b/src/aiogram_dialog/api/internal/widgets.py
index ba51d328..c3976817 100644
--- a/src/aiogram_dialog/api/internal/widgets.py
+++ b/src/aiogram_dialog/api/internal/widgets.py
@@ -1,12 +1,18 @@
from abc import abstractmethod
+from collections.abc import Awaitable, Callable
from typing import (
- Any, Optional, Protocol,
- runtime_checkable, Union,
+ Any,
+ Optional,
+ Protocol,
+ Union,
+ runtime_checkable,
)
-from collections.abc import Awaitable, Callable
from aiogram.types import (
- CallbackQuery, InlineKeyboardButton, KeyboardButton, Message,
+ CallbackQuery,
+ InlineKeyboardButton,
+ KeyboardButton,
+ Message,
)
from aiogram_dialog import DialogManager
diff --git a/src/aiogram_dialog/api/internal/window.py b/src/aiogram_dialog/api/internal/window.py
index 2dce844c..9deb8d59 100644
--- a/src/aiogram_dialog/api/internal/window.py
+++ b/src/aiogram_dialog/api/internal/window.py
@@ -9,6 +9,7 @@
from aiogram_dialog.api.entities import Data, NewMessage
from aiogram_dialog.api.protocols import DialogProtocol
+
from .manager import DialogManager
diff --git a/src/aiogram_dialog/api/protocols/__init__.py b/src/aiogram_dialog/api/protocols/__init__.py
index 73f1ecb1..731dd00c 100644
--- a/src/aiogram_dialog/api/protocols/__init__.py
+++ b/src/aiogram_dialog/api/protocols/__init__.py
@@ -9,7 +9,10 @@
from .dialog import CancelEventProcessing, DialogProtocol
from .manager import (
- BaseDialogManager, BgManagerFactory, DialogManager, UnsetId,
+ BaseDialogManager,
+ BgManagerFactory,
+ DialogManager,
+ UnsetId,
)
from .media import MediaIdStorageProtocol
from .message_manager import MessageManagerProtocol, MessageNotModified
diff --git a/src/aiogram_dialog/api/protocols/dialog.py b/src/aiogram_dialog/api/protocols/dialog.py
index 5960aa37..024dbfff 100644
--- a/src/aiogram_dialog/api/protocols/dialog.py
+++ b/src/aiogram_dialog/api/protocols/dialog.py
@@ -4,8 +4,11 @@
from aiogram.fsm.state import State, StatesGroup
from aiogram_dialog.api.entities import (
- Data, LaunchMode, NewMessage,
+ Data,
+ LaunchMode,
+ NewMessage,
)
+
from .manager import DialogManager
diff --git a/src/aiogram_dialog/api/protocols/manager.py b/src/aiogram_dialog/api/protocols/manager.py
index e578ecc5..cffd5bdb 100644
--- a/src/aiogram_dialog/api/protocols/manager.py
+++ b/src/aiogram_dialog/api/protocols/manager.py
@@ -7,7 +7,12 @@
from aiogram_dialog.api.entities import (
AccessSettings,
- ChatEvent, Context, Data, ShowMode, Stack, StartMode,
+ ChatEvent,
+ Context,
+ Data,
+ ShowMode,
+ Stack,
+ StartMode,
)
diff --git a/src/aiogram_dialog/context/access_validator.py b/src/aiogram_dialog/context/access_validator.py
index 1120be57..b9dbebe7 100644
--- a/src/aiogram_dialog/context/access_validator.py
+++ b/src/aiogram_dialog/context/access_validator.py
@@ -5,7 +5,8 @@
from aiogram_dialog import ChatEvent
from aiogram_dialog.api.entities import (
- Context, Stack,
+ Context,
+ Stack,
)
from aiogram_dialog.api.protocols import StackAccessValidator
diff --git a/src/aiogram_dialog/context/intent_middleware.py b/src/aiogram_dialog/context/intent_middleware.py
index f19cc7a1..069c9ff5 100644
--- a/src/aiogram_dialog/context/intent_middleware.py
+++ b/src/aiogram_dialog/context/intent_middleware.py
@@ -1,6 +1,6 @@
+from collections.abc import Awaitable, Callable
from logging import getLogger
from typing import Any, Optional
-from collections.abc import Awaitable, Callable
from aiogram import Router
from aiogram.dispatcher.event.bases import UNHANDLED
@@ -10,30 +10,40 @@
CallbackQuery,
ChatJoinRequest,
ChatMemberUpdated,
- InaccessibleMessage, Message,
+ InaccessibleMessage,
+ Message,
)
from aiogram.types.error_event import ErrorEvent
from aiogram_dialog.api.entities import (
+ DEFAULT_STACK_ID,
+ EVENT_CONTEXT_KEY,
ChatEvent,
Context,
- DEFAULT_STACK_ID,
DialogUpdateEvent,
- EVENT_CONTEXT_KEY,
EventContext,
Stack,
)
from aiogram_dialog.api.exceptions import (
- InvalidStackIdError, OutdatedIntent, UnknownIntent, UnknownState,
+ InvalidStackIdError,
+ OutdatedIntent,
+ UnknownIntent,
+ UnknownState,
)
from aiogram_dialog.api.internal import (
- CALLBACK_DATA_KEY, CONTEXT_KEY, EVENT_SIMULATED,
- ReplyCallbackQuery, STACK_KEY, STORAGE_KEY,
+ CALLBACK_DATA_KEY,
+ CONTEXT_KEY,
+ EVENT_SIMULATED,
+ STACK_KEY,
+ STORAGE_KEY,
+ ReplyCallbackQuery,
)
from aiogram_dialog.api.protocols import (
- DialogRegistryProtocol, StackAccessValidator,
+ DialogRegistryProtocol,
+ StackAccessValidator,
)
from aiogram_dialog.utils import remove_intent_id, split_reply_callback
+
from .storage import StorageProxy
logger = getLogger(__name__)
diff --git a/src/aiogram_dialog/context/storage.py b/src/aiogram_dialog/context/storage.py
index b6c39e7d..bd99102a 100644
--- a/src/aiogram_dialog/context/storage.py
+++ b/src/aiogram_dialog/context/storage.py
@@ -5,11 +5,16 @@
from aiogram import Bot
from aiogram.fsm.state import State, StatesGroup
from aiogram.fsm.storage.base import (
- BaseEventIsolation, BaseStorage, StorageKey,
+ BaseEventIsolation,
+ BaseStorage,
+ StorageKey,
)
from aiogram_dialog.api.entities import (
- AccessSettings, Context, DEFAULT_STACK_ID, Stack,
+ DEFAULT_STACK_ID,
+ AccessSettings,
+ Context,
+ Stack,
)
from aiogram_dialog.api.exceptions import UnknownIntent, UnknownState
diff --git a/src/aiogram_dialog/dialog.py b/src/aiogram_dialog/dialog.py
index 5da26c73..c9571c7e 100644
--- a/src/aiogram_dialog/dialog.py
+++ b/src/aiogram_dialog/dialog.py
@@ -18,12 +18,15 @@
)
from aiogram_dialog.api.internal import Widget, WindowProtocol
from aiogram_dialog.api.protocols import (
- CancelEventProcessing, DialogManager, DialogProtocol,
+ CancelEventProcessing,
+ DialogManager,
+ DialogProtocol,
)
+
from .context.intent_filter import IntentFilter
from .utils import remove_intent_id
from .widgets.data import PreviewAwareGetter
-from .widgets.utils import ensure_data_getter, GetterVariant
+from .widgets.utils import GetterVariant, ensure_data_getter
logger = getLogger(__name__)
diff --git a/src/aiogram_dialog/manager/bg_manager.py b/src/aiogram_dialog/manager/bg_manager.py
index dfd05c74..2d9c4136 100644
--- a/src/aiogram_dialog/manager/bg_manager.py
+++ b/src/aiogram_dialog/manager/bg_manager.py
@@ -6,9 +6,9 @@
from aiogram.types import Chat, User
from aiogram_dialog.api.entities import (
+ DEFAULT_STACK_ID,
AccessSettings,
Data,
- DEFAULT_STACK_ID,
DialogAction,
DialogStartEvent,
DialogSwitchEvent,
@@ -19,10 +19,13 @@
StartMode,
)
from aiogram_dialog.api.internal import (
- FakeChat, FakeUser,
+ FakeChat,
+ FakeUser,
)
from aiogram_dialog.api.protocols import (
- BaseDialogManager, BgManagerFactory, UnsetId,
+ BaseDialogManager,
+ BgManagerFactory,
+ UnsetId,
)
from aiogram_dialog.manager.updater import Updater
from aiogram_dialog.utils import is_chat_loaded, is_user_loaded
diff --git a/src/aiogram_dialog/manager/manager.py b/src/aiogram_dialog/manager/manager.py
index b310b381..86837b03 100644
--- a/src/aiogram_dialog/manager/manager.py
+++ b/src/aiogram_dialog/manager/manager.py
@@ -1,49 +1,68 @@
from copy import deepcopy
from logging import getLogger
-from typing import Any, cast, Optional, Union
+from typing import Any, Optional, Union, cast
from aiogram import Router
from aiogram.enums import ChatType
from aiogram.fsm.state import State
from aiogram.types import (
- CallbackQuery, Chat, ErrorEvent, Message, ReplyKeyboardMarkup, User,
+ CallbackQuery,
+ Chat,
+ ErrorEvent,
+ Message,
+ ReplyKeyboardMarkup,
+ User,
)
from aiogram_dialog.api.entities import (
+ DEFAULT_STACK_ID,
+ EVENT_CONTEXT_KEY,
AccessSettings,
ChatEvent,
Context,
Data,
- DEFAULT_STACK_ID,
- EVENT_CONTEXT_KEY,
EventContext,
LaunchMode,
MediaId,
NewMessage,
+ OldMessage,
ShowMode,
Stack,
StartMode,
+ UnknownText,
)
-from aiogram_dialog.api.entities import OldMessage, UnknownText
from aiogram_dialog.api.exceptions import (
- IncorrectBackgroundError, InvalidKeyboardType, NoContextError,
+ IncorrectBackgroundError,
+ InvalidKeyboardType,
+ NoContextError,
)
from aiogram_dialog.api.internal import (
- CONTEXT_KEY, EVENT_SIMULATED, FakeChat, FakeUser,
- STACK_KEY, STORAGE_KEY,
+ CONTEXT_KEY,
+ EVENT_SIMULATED,
+ STACK_KEY,
+ STORAGE_KEY,
+ FakeChat,
+ FakeUser,
)
from aiogram_dialog.api.protocols import (
- BaseDialogManager, DialogManager, DialogProtocol, DialogRegistryProtocol,
- MediaIdStorageProtocol, MessageManagerProtocol, MessageNotModified,
+ BaseDialogManager,
+ DialogManager,
+ DialogProtocol,
+ DialogRegistryProtocol,
+ MediaIdStorageProtocol,
+ MessageManagerProtocol,
+ MessageNotModified,
UnsetId,
)
from aiogram_dialog.context.storage import StorageProxy
from aiogram_dialog.utils import get_media_id
+
from .bg_manager import (
BgManager,
coalesce_business_connection_id,
coalesce_thread_id,
)
+
logger = getLogger(__name__)
diff --git a/src/aiogram_dialog/manager/manager_factory.py b/src/aiogram_dialog/manager/manager_factory.py
index aafa263a..ae364e14 100644
--- a/src/aiogram_dialog/manager/manager_factory.py
+++ b/src/aiogram_dialog/manager/manager_factory.py
@@ -3,9 +3,12 @@
from aiogram_dialog.api.entities import ChatEvent
from aiogram_dialog.api.internal import DialogManagerFactory
from aiogram_dialog.api.protocols import (
- DialogManager, DialogRegistryProtocol,
- MediaIdStorageProtocol, MessageManagerProtocol,
+ DialogManager,
+ DialogRegistryProtocol,
+ MediaIdStorageProtocol,
+ MessageManagerProtocol,
)
+
from .manager import ManagerImpl
diff --git a/src/aiogram_dialog/manager/manager_middleware.py b/src/aiogram_dialog/manager/manager_middleware.py
index 2166eaae..041a7d71 100644
--- a/src/aiogram_dialog/manager/manager_middleware.py
+++ b/src/aiogram_dialog/manager/manager_middleware.py
@@ -1,14 +1,16 @@
-from typing import Any, Union
from collections.abc import Awaitable, Callable
+from typing import Any, Union
from aiogram import Router
from aiogram.dispatcher.middlewares.base import BaseMiddleware
from aiogram.types import TelegramObject, Update
from aiogram_dialog.api.entities import ChatEvent, DialogUpdateEvent
-from aiogram_dialog.api.internal import DialogManagerFactory, STORAGE_KEY
+from aiogram_dialog.api.internal import STORAGE_KEY, DialogManagerFactory
from aiogram_dialog.api.protocols import (
- BgManagerFactory, DialogManager, DialogRegistryProtocol,
+ BgManagerFactory,
+ DialogManager,
+ DialogRegistryProtocol,
)
MANAGER_KEY = "dialog_manager"
diff --git a/src/aiogram_dialog/manager/message_manager.py b/src/aiogram_dialog/manager/message_manager.py
index 773c9cb2..d3d76a9f 100644
--- a/src/aiogram_dialog/manager/message_manager.py
+++ b/src/aiogram_dialog/manager/message_manager.py
@@ -20,10 +20,15 @@
)
from aiogram_dialog.api.entities import (
- MediaAttachment, MediaId, NewMessage, OldMessage, ShowMode,
+ MediaAttachment,
+ MediaId,
+ NewMessage,
+ OldMessage,
+ ShowMode,
)
from aiogram_dialog.api.protocols import (
- MessageManagerProtocol, MessageNotModified,
+ MessageManagerProtocol,
+ MessageNotModified,
)
from aiogram_dialog.utils import get_media_id
diff --git a/src/aiogram_dialog/manager/sub_manager.py b/src/aiogram_dialog/manager/sub_manager.py
index 6767e6dc..5977cf5a 100644
--- a/src/aiogram_dialog/manager/sub_manager.py
+++ b/src/aiogram_dialog/manager/sub_manager.py
@@ -6,12 +6,18 @@
from aiogram_dialog.api.entities import (
AccessSettings,
- ChatEvent, Data, ShowMode, StartMode,
+ ChatEvent,
+ Context,
+ Data,
+ ShowMode,
+ Stack,
+ StartMode,
)
-from aiogram_dialog.api.entities import Context, Stack
from aiogram_dialog.api.internal import Widget
from aiogram_dialog.api.protocols import (
- BaseDialogManager, DialogManager, UnsetId,
+ BaseDialogManager,
+ DialogManager,
+ UnsetId,
)
diff --git a/src/aiogram_dialog/setup.py b/src/aiogram_dialog/setup.py
index 7eb5eac5..e26b12b5 100644
--- a/src/aiogram_dialog/setup.py
+++ b/src/aiogram_dialog/setup.py
@@ -1,9 +1,9 @@
-from typing import Optional, Union
from collections.abc import Callable, Iterable
+from typing import Optional, Union
from aiogram import Router
from aiogram.dispatcher.event.telegram import TelegramEventObserver
-from aiogram.fsm.state import any_state, State, StatesGroup
+from aiogram.fsm.state import State, StatesGroup, any_state
from aiogram.fsm.storage.base import BaseEventIsolation
from aiogram.fsm.storage.memory import SimpleEventIsolation
@@ -11,23 +11,29 @@
from aiogram_dialog.api.exceptions import UnregisteredDialogError
from aiogram_dialog.api.internal import DialogManagerFactory
from aiogram_dialog.api.protocols import (
- BgManagerFactory, DialogProtocol, DialogRegistryProtocol,
- MediaIdStorageProtocol, MessageManagerProtocol, StackAccessValidator,
+ BgManagerFactory,
+ DialogProtocol,
+ DialogRegistryProtocol,
+ MediaIdStorageProtocol,
+ MessageManagerProtocol,
+ StackAccessValidator,
)
from aiogram_dialog.context.intent_middleware import (
- context_saver_middleware,
- context_unlocker_middleware,
IntentErrorMiddleware,
IntentMiddlewareFactory,
+ context_saver_middleware,
+ context_unlocker_middleware,
)
from aiogram_dialog.context.media_storage import MediaIdStorage
from aiogram_dialog.manager.bg_manager import BgManagerFactoryImpl
from aiogram_dialog.manager.manager_factory import DefaultManagerFactory
from aiogram_dialog.manager.manager_middleware import (
- BgFactoryMiddleware, ManagerMiddleware,
+ BgFactoryMiddleware,
+ ManagerMiddleware,
)
from aiogram_dialog.manager.message_manager import MessageManager
from aiogram_dialog.manager.update_handler import handle_update
+
from .about import about_dialog
from .context.access_validator import DefaultAccessValidator
diff --git a/src/aiogram_dialog/test_tools/bot_client.py b/src/aiogram_dialog/test_tools/bot_client.py
index 961b5a92..e0426870 100644
--- a/src/aiogram_dialog/test_tools/bot_client.py
+++ b/src/aiogram_dialog/test_tools/bot_client.py
@@ -5,10 +5,20 @@
from aiogram import Bot, Dispatcher
from aiogram.methods import AnswerCallbackQuery, TelegramMethod
from aiogram.types import (
- CallbackQuery, Chat, ChatJoinRequest,
- ChatMemberAdministrator, ChatMemberBanned, ChatMemberLeft,
- ChatMemberMember, ChatMemberOwner, ChatMemberRestricted, ChatMemberUpdated,
- InlineKeyboardButton, Message, Update, User,
+ CallbackQuery,
+ Chat,
+ ChatJoinRequest,
+ ChatMemberAdministrator,
+ ChatMemberBanned,
+ ChatMemberLeft,
+ ChatMemberMember,
+ ChatMemberOwner,
+ ChatMemberRestricted,
+ ChatMemberUpdated,
+ InlineKeyboardButton,
+ Message,
+ Update,
+ User,
)
from .keyboard import InlineButtonLocator
diff --git a/src/aiogram_dialog/test_tools/memory_storage.py b/src/aiogram_dialog/test_tools/memory_storage.py
index f8112c34..de2ecad3 100644
--- a/src/aiogram_dialog/test_tools/memory_storage.py
+++ b/src/aiogram_dialog/test_tools/memory_storage.py
@@ -6,7 +6,6 @@
from aiogram.fsm.state import State
from aiogram.fsm.storage.base import BaseStorage, StorageKey
-
StateType = Optional[Union[str, State]]
diff --git a/src/aiogram_dialog/test_tools/mock_message_manager.py b/src/aiogram_dialog/test_tools/mock_message_manager.py
index 8a526da3..2fd2444e 100644
--- a/src/aiogram_dialog/test_tools/mock_message_manager.py
+++ b/src/aiogram_dialog/test_tools/mock_message_manager.py
@@ -5,14 +5,20 @@
from aiogram import Bot
from aiogram.types import (
- Audio, CallbackQuery, Document, Message, PhotoSize, ReplyKeyboardMarkup,
+ Audio,
+ CallbackQuery,
+ Document,
+ Message,
+ PhotoSize,
+ ReplyKeyboardMarkup,
Video,
)
from aiogram_dialog import ShowMode
from aiogram_dialog.api.entities import MediaAttachment, NewMessage, OldMessage
from aiogram_dialog.api.protocols import (
- MessageManagerProtocol, MessageNotModified,
+ MessageManagerProtocol,
+ MessageNotModified,
)
diff --git a/src/aiogram_dialog/tools/preview.py b/src/aiogram_dialog/tools/preview.py
index aa2ae080..a9e1c190 100644
--- a/src/aiogram_dialog/tools/preview.py
+++ b/src/aiogram_dialog/tools/preview.py
@@ -24,13 +24,13 @@
DialogProtocol,
)
from aiogram_dialog.api.entities import (
+ EVENT_CONTEXT_KEY,
AccessSettings,
ChatEvent,
Context,
Data,
DialogAction,
DialogUpdateEvent,
- EVENT_CONTEXT_KEY,
EventContext,
MediaAttachment,
NewMessage,
diff --git a/src/aiogram_dialog/utils.py b/src/aiogram_dialog/utils.py
index 023b4a77..de1f7768 100644
--- a/src/aiogram_dialog/utils.py
+++ b/src/aiogram_dialog/utils.py
@@ -14,7 +14,9 @@
)
from aiogram_dialog.api.entities import (
- ChatEvent, DialogUpdateEvent, MediaId,
+ ChatEvent,
+ DialogUpdateEvent,
+ MediaId,
)
from aiogram_dialog.api.internal import RawKeyboard
diff --git a/src/aiogram_dialog/widgets/common/__init__.py b/src/aiogram_dialog/widgets/common/__init__.py
index bc59f780..1dcad9bc 100644
--- a/src/aiogram_dialog/widgets/common/__init__.py
+++ b/src/aiogram_dialog/widgets/common/__init__.py
@@ -24,4 +24,4 @@
Scroll,
sync_scroll,
)
-from .when import true_condition, Whenable, WhenCondition
+from .when import Whenable, WhenCondition, true_condition
diff --git a/src/aiogram_dialog/widgets/common/action.py b/src/aiogram_dialog/widgets/common/action.py
index 1246e78f..4f460049 100644
--- a/src/aiogram_dialog/widgets/common/action.py
+++ b/src/aiogram_dialog/widgets/common/action.py
@@ -3,6 +3,7 @@
from aiogram_dialog.api.exceptions import InvalidWidgetIdError
from aiogram_dialog.api.protocols import DialogManager
+
from .base import BaseWidget
ID_PATTERN = re.compile("^[a-zA-Z0-9_.]+$")
diff --git a/src/aiogram_dialog/widgets/common/items.py b/src/aiogram_dialog/widgets/common/items.py
index bac707ac..6419f3d4 100644
--- a/src/aiogram_dialog/widgets/common/items.py
+++ b/src/aiogram_dialog/widgets/common/items.py
@@ -1,6 +1,6 @@
+from collections.abc import Callable, Sequence
from operator import itemgetter
from typing import Union
-from collections.abc import Callable, Sequence
from magic_filter import MagicFilter
diff --git a/src/aiogram_dialog/widgets/common/scroll.py b/src/aiogram_dialog/widgets/common/scroll.py
index bd9e0e9e..42ba21ac 100644
--- a/src/aiogram_dialog/widgets/common/scroll.py
+++ b/src/aiogram_dialog/widgets/common/scroll.py
@@ -1,13 +1,15 @@
from abc import ABC, abstractmethod
-from typing import Protocol, Union
from collections.abc import Awaitable, Callable, Sequence
+from typing import Protocol, Union
from aiogram_dialog.api.entities import ChatEvent
from aiogram_dialog.api.internal import Widget
from aiogram_dialog.api.protocols import DialogManager
from aiogram_dialog.widgets.widget_event import (
- ensure_event_processor, WidgetEventProcessor,
+ WidgetEventProcessor,
+ ensure_event_processor,
)
+
from .action import Actionable
from .managed import ManagedWidget
diff --git a/src/aiogram_dialog/widgets/input/base.py b/src/aiogram_dialog/widgets/input/base.py
index ed893835..b9f3e1a3 100644
--- a/src/aiogram_dialog/widgets/input/base.py
+++ b/src/aiogram_dialog/widgets/input/base.py
@@ -1,6 +1,6 @@
from abc import abstractmethod
-from typing import Any, Optional, Union
from collections.abc import Awaitable, Callable, Sequence
+from typing import Any, Optional, Union
from aiogram import F
from aiogram.dispatcher.event.handler import FilterObject
@@ -8,12 +8,13 @@
from aiogram_dialog.api.internal import InputWidget
from aiogram_dialog.api.protocols import (
- DialogManager, DialogProtocol,
+ DialogManager,
+ DialogProtocol,
)
from aiogram_dialog.widgets.common import Actionable
from aiogram_dialog.widgets.widget_event import (
- ensure_event_processor,
WidgetEventProcessor,
+ ensure_event_processor,
)
MessageHandlerFunc = Callable[
diff --git a/src/aiogram_dialog/widgets/input/combined.py b/src/aiogram_dialog/widgets/input/combined.py
index c9194624..b0f8078c 100644
--- a/src/aiogram_dialog/widgets/input/combined.py
+++ b/src/aiogram_dialog/widgets/input/combined.py
@@ -1,12 +1,14 @@
-from typing import Any, Optional
from collections.abc import Callable
+from typing import Any, Optional
from aiogram.dispatcher.event.handler import FilterObject
from aiogram.types import Message
from aiogram_dialog.api.protocols import (
- DialogManager, DialogProtocol,
+ DialogManager,
+ DialogProtocol,
)
+
from .base import BaseInput
diff --git a/src/aiogram_dialog/widgets/input/text.py b/src/aiogram_dialog/widgets/input/text.py
index cd87b3e6..27029008 100644
--- a/src/aiogram_dialog/widgets/input/text.py
+++ b/src/aiogram_dialog/widgets/input/text.py
@@ -1,6 +1,7 @@
from __future__ import annotations
from abc import abstractmethod
+from collections.abc import Callable
from typing import (
Any,
Generic,
@@ -9,7 +10,6 @@
TypeVar,
Union,
)
-from collections.abc import Callable
from aiogram.dispatcher.event.handler import FilterObject
from aiogram.types import ContentType, Message
@@ -17,9 +17,10 @@
from aiogram_dialog.api.protocols import DialogManager, DialogProtocol
from aiogram_dialog.widgets.common import ManagedWidget
from aiogram_dialog.widgets.widget_event import (
- ensure_event_processor,
WidgetEventProcessor,
+ ensure_event_processor,
)
+
from .base import BaseInput
T = TypeVar("T")
diff --git a/src/aiogram_dialog/widgets/kbd/__init__.py b/src/aiogram_dialog/widgets/kbd/__init__.py
index 07b67b98..52dfc1ee 100644
--- a/src/aiogram_dialog/widgets/kbd/__init__.py
+++ b/src/aiogram_dialog/widgets/kbd/__init__.py
@@ -46,7 +46,10 @@
from .base import Keyboard
from .button import Button, SwitchInlineQuery, Url, WebApp
from .calendar_kbd import (
- Calendar, CalendarConfig, CalendarScope, CalendarUserConfig,
+ Calendar,
+ CalendarConfig,
+ CalendarScope,
+ CalendarUserConfig,
ManagedCalendar,
)
from .checkbox import Checkbox, ManagedCheckbox
diff --git a/src/aiogram_dialog/widgets/kbd/button.py b/src/aiogram_dialog/widgets/kbd/button.py
index 37e5355a..21f99dca 100644
--- a/src/aiogram_dialog/widgets/kbd/button.py
+++ b/src/aiogram_dialog/widgets/kbd/button.py
@@ -1,5 +1,5 @@
-from typing import Optional, Union
from collections.abc import Awaitable, Callable
+from typing import Optional, Union
from aiogram.types import CallbackQuery, InlineKeyboardButton, WebAppInfo
@@ -8,9 +8,10 @@
from aiogram_dialog.widgets.common import WhenCondition
from aiogram_dialog.widgets.text import Text
from aiogram_dialog.widgets.widget_event import (
- ensure_event_processor,
WidgetEventProcessor,
+ ensure_event_processor,
)
+
from .base import Keyboard
OnClick = Callable[[CallbackQuery, "Button", DialogManager], Awaitable]
diff --git a/src/aiogram_dialog/widgets/kbd/calendar_kbd.py b/src/aiogram_dialog/widgets/kbd/calendar_kbd.py
index 2ee1b07a..7d4aafa1 100644
--- a/src/aiogram_dialog/widgets/kbd/calendar_kbd.py
+++ b/src/aiogram_dialog/widgets/kbd/calendar_kbd.py
@@ -21,8 +21,10 @@
from aiogram_dialog.widgets.common import ManagedWidget, WhenCondition
from aiogram_dialog.widgets.text import Format, Text
from aiogram_dialog.widgets.widget_event import (
- ensure_event_processor, WidgetEventProcessor,
+ WidgetEventProcessor,
+ ensure_event_processor,
)
+
from .base import Keyboard
EPOCH = date(1970, 1, 1)
diff --git a/src/aiogram_dialog/widgets/kbd/checkbox.py b/src/aiogram_dialog/widgets/kbd/checkbox.py
index 7b0c21c1..973b040d 100644
--- a/src/aiogram_dialog/widgets/kbd/checkbox.py
+++ b/src/aiogram_dialog/widgets/kbd/checkbox.py
@@ -1,6 +1,6 @@
from abc import ABC, abstractmethod
-from typing import Optional, Union
from collections.abc import Awaitable, Callable
+from typing import Optional, Union
from aiogram.types import CallbackQuery, InlineKeyboardButton
@@ -10,9 +10,10 @@
from aiogram_dialog.widgets.common import ManagedWidget, WhenCondition
from aiogram_dialog.widgets.text import Case, Text
from aiogram_dialog.widgets.widget_event import (
- ensure_event_processor,
WidgetEventProcessor,
+ ensure_event_processor,
)
+
from .base import Keyboard
OnStateChanged = Callable[
diff --git a/src/aiogram_dialog/widgets/kbd/counter.py b/src/aiogram_dialog/widgets/kbd/counter.py
index a034c1ee..86271f7a 100644
--- a/src/aiogram_dialog/widgets/kbd/counter.py
+++ b/src/aiogram_dialog/widgets/kbd/counter.py
@@ -10,8 +10,8 @@
from aiogram_dialog.widgets.kbd.base import Keyboard
from aiogram_dialog.widgets.text import Const, Format, Text
from aiogram_dialog.widgets.widget_event import (
- ensure_event_processor,
WidgetEventProcessor,
+ ensure_event_processor,
)
diff --git a/src/aiogram_dialog/widgets/kbd/group.py b/src/aiogram_dialog/widgets/kbd/group.py
index 02d9e6b8..ef526b52 100644
--- a/src/aiogram_dialog/widgets/kbd/group.py
+++ b/src/aiogram_dialog/widgets/kbd/group.py
@@ -1,12 +1,13 @@
+from collections.abc import Iterable
from itertools import chain
from typing import Optional
-from collections.abc import Iterable
from aiogram.types import CallbackQuery, InlineKeyboardButton
from aiogram_dialog.api.internal import ButtonVariant, RawKeyboard
from aiogram_dialog.api.protocols import DialogManager, DialogProtocol
from aiogram_dialog.widgets.common import WhenCondition
+
from .base import Keyboard
diff --git a/src/aiogram_dialog/widgets/kbd/list_group.py b/src/aiogram_dialog/widgets/kbd/list_group.py
index 499e1ce1..16454705 100644
--- a/src/aiogram_dialog/widgets/kbd/list_group.py
+++ b/src/aiogram_dialog/widgets/kbd/list_group.py
@@ -1,20 +1,22 @@
-from typing import Any, Optional, Union
from collections.abc import Callable
+from typing import Any, Optional, Union
from aiogram.types import CallbackQuery
from aiogram_dialog.api.internal import RawKeyboard, Widget
from aiogram_dialog.api.protocols import (
- DialogManager, DialogProtocol,
+ DialogManager,
+ DialogProtocol,
)
from aiogram_dialog.manager.sub_manager import SubManager
from aiogram_dialog.widgets.common import ManagedWidget, WhenCondition
-from .base import Keyboard
from aiogram_dialog.widgets.common.items import (
- get_items_getter,
ItemsGetterVariant,
+ get_items_getter,
)
+from .base import Keyboard
+
ItemIdGetter = Callable[[Any], Union[str, int]]
diff --git a/src/aiogram_dialog/widgets/kbd/pager.py b/src/aiogram_dialog/widgets/kbd/pager.py
index e4958160..b5c016ec 100644
--- a/src/aiogram_dialog/widgets/kbd/pager.py
+++ b/src/aiogram_dialog/widgets/kbd/pager.py
@@ -8,6 +8,7 @@
from aiogram_dialog.api.protocols import DialogManager, DialogProtocol
from aiogram_dialog.widgets.common import ManagedScroll, Scroll, WhenCondition
from aiogram_dialog.widgets.text import Const, Format, Text
+
from .base import Keyboard
diff --git a/src/aiogram_dialog/widgets/kbd/request.py b/src/aiogram_dialog/widgets/kbd/request.py
index 6dc9576e..5625652f 100644
--- a/src/aiogram_dialog/widgets/kbd/request.py
+++ b/src/aiogram_dialog/widgets/kbd/request.py
@@ -1,11 +1,12 @@
-from typing import Union
from collections.abc import Callable
+from typing import Union
from aiogram.types import KeyboardButton
from aiogram_dialog.api.internal import RawKeyboard
from aiogram_dialog.api.protocols import DialogManager
from aiogram_dialog.widgets.text import Text
+
from .base import Keyboard
diff --git a/src/aiogram_dialog/widgets/kbd/scrolling_group.py b/src/aiogram_dialog/widgets/kbd/scrolling_group.py
index 015d6165..acf6d168 100644
--- a/src/aiogram_dialog/widgets/kbd/scrolling_group.py
+++ b/src/aiogram_dialog/widgets/kbd/scrolling_group.py
@@ -5,8 +5,11 @@
from aiogram_dialog.api.internal import RawKeyboard
from aiogram_dialog.api.protocols import DialogManager, DialogProtocol
from aiogram_dialog.widgets.common import (
- BaseScroll, OnPageChangedVariants, WhenCondition,
+ BaseScroll,
+ OnPageChangedVariants,
+ WhenCondition,
)
+
from .base import Keyboard
from .group import Group
diff --git a/src/aiogram_dialog/widgets/kbd/select.py b/src/aiogram_dialog/widgets/kbd/select.py
index 5596c7a8..320df9d9 100644
--- a/src/aiogram_dialog/widgets/kbd/select.py
+++ b/src/aiogram_dialog/widgets/kbd/select.py
@@ -16,14 +16,15 @@
from aiogram_dialog.api.protocols import DialogManager, DialogProtocol
from aiogram_dialog.widgets.common import ManagedWidget, WhenCondition
from aiogram_dialog.widgets.common.items import (
- get_items_getter,
ItemsGetterVariant,
+ get_items_getter,
)
from aiogram_dialog.widgets.text import Case, Text
from aiogram_dialog.widgets.widget_event import (
- ensure_event_processor,
WidgetEventProcessor,
+ ensure_event_processor,
)
+
from .base import Keyboard
T = TypeVar("T")
diff --git a/src/aiogram_dialog/widgets/kbd/stub_scroll.py b/src/aiogram_dialog/widgets/kbd/stub_scroll.py
index 5d3b5178..7910f1ca 100644
--- a/src/aiogram_dialog/widgets/kbd/stub_scroll.py
+++ b/src/aiogram_dialog/widgets/kbd/stub_scroll.py
@@ -1,16 +1,17 @@
-from typing import Union
from collections.abc import Callable
+from typing import Union
from magic_filter import MagicFilter
from aiogram_dialog.api.internal import RawKeyboard
from aiogram_dialog.api.protocols import DialogManager
-from .base import Keyboard
from aiogram_dialog.widgets.common.scroll import (
BaseScroll,
OnPageChangedVariants,
)
+from .base import Keyboard
+
PagesGetter = Callable[[dict, "StubScroll", DialogManager], int]
diff --git a/src/aiogram_dialog/widgets/markup/force_reply.py b/src/aiogram_dialog/widgets/markup/force_reply.py
index 5673ca70..0c6be743 100644
--- a/src/aiogram_dialog/widgets/markup/force_reply.py
+++ b/src/aiogram_dialog/widgets/markup/force_reply.py
@@ -4,7 +4,9 @@
from aiogram_dialog import DialogManager
from aiogram_dialog.api.internal.widgets import (
- MarkupFactory, MarkupVariant, RawKeyboard,
+ MarkupFactory,
+ MarkupVariant,
+ RawKeyboard,
)
from aiogram_dialog.widgets.text import Text
diff --git a/src/aiogram_dialog/widgets/markup/inline_keyboard.py b/src/aiogram_dialog/widgets/markup/inline_keyboard.py
index 47352a8a..2e918ca6 100644
--- a/src/aiogram_dialog/widgets/markup/inline_keyboard.py
+++ b/src/aiogram_dialog/widgets/markup/inline_keyboard.py
@@ -2,7 +2,9 @@
from aiogram_dialog import DialogManager
from aiogram_dialog.api.internal.widgets import (
- MarkupFactory, MarkupVariant, RawKeyboard,
+ MarkupFactory,
+ MarkupVariant,
+ RawKeyboard,
)
from aiogram_dialog.utils import add_intent_id
diff --git a/src/aiogram_dialog/widgets/markup/reply_keyboard.py b/src/aiogram_dialog/widgets/markup/reply_keyboard.py
index a5dca48a..74a8891f 100644
--- a/src/aiogram_dialog/widgets/markup/reply_keyboard.py
+++ b/src/aiogram_dialog/widgets/markup/reply_keyboard.py
@@ -4,7 +4,9 @@
from aiogram_dialog import DialogManager
from aiogram_dialog.api.internal.widgets import (
- MarkupFactory, MarkupVariant, RawKeyboard,
+ MarkupFactory,
+ MarkupVariant,
+ RawKeyboard,
)
from aiogram_dialog.utils import add_intent_id, transform_to_reply_keyboard
from aiogram_dialog.widgets.text import Text
diff --git a/src/aiogram_dialog/widgets/media/dynamic.py b/src/aiogram_dialog/widgets/media/dynamic.py
index 3b602f7f..3a0523f2 100644
--- a/src/aiogram_dialog/widgets/media/dynamic.py
+++ b/src/aiogram_dialog/widgets/media/dynamic.py
@@ -5,9 +5,9 @@
https://github.com/SamWarden/aiogram_dialog_extras
"""
+from collections.abc import Callable
from operator import itemgetter
from typing import Optional, Union
-from collections.abc import Callable
from aiogram_dialog import DialogManager
from aiogram_dialog.api.entities import MediaAttachment
diff --git a/src/aiogram_dialog/widgets/media/scroll.py b/src/aiogram_dialog/widgets/media/scroll.py
index 34bee7cb..5c5a5b93 100644
--- a/src/aiogram_dialog/widgets/media/scroll.py
+++ b/src/aiogram_dialog/widgets/media/scroll.py
@@ -3,14 +3,17 @@
from aiogram_dialog.api.entities import MediaAttachment
from aiogram_dialog.api.protocols import DialogManager
from aiogram_dialog.widgets.common import (
- BaseScroll, OnPageChangedVariants, WhenCondition,
+ BaseScroll,
+ OnPageChangedVariants,
+ WhenCondition,
)
-from .base import Media
from aiogram_dialog.widgets.common.items import (
- get_items_getter,
ItemsGetterVariant,
+ get_items_getter,
)
+from .base import Media
+
class MediaScroll(Media, BaseScroll):
def __init__(
diff --git a/src/aiogram_dialog/widgets/media/static.py b/src/aiogram_dialog/widgets/media/static.py
index 43f1af7d..8053d150 100644
--- a/src/aiogram_dialog/widgets/media/static.py
+++ b/src/aiogram_dialog/widgets/media/static.py
@@ -7,6 +7,7 @@
from aiogram_dialog.api.protocols import DialogManager
from aiogram_dialog.widgets.common import WhenCondition
from aiogram_dialog.widgets.text import Const, Text
+
from .base import Media
diff --git a/src/aiogram_dialog/widgets/text/base.py b/src/aiogram_dialog/widgets/text/base.py
index 726f38da..f5e80877 100644
--- a/src/aiogram_dialog/widgets/text/base.py
+++ b/src/aiogram_dialog/widgets/text/base.py
@@ -4,7 +4,10 @@
from aiogram_dialog.api.internal import TextWidget
from aiogram_dialog.api.protocols import DialogManager
from aiogram_dialog.widgets.common import (
- BaseWidget, true_condition, Whenable, WhenCondition,
+ BaseWidget,
+ Whenable,
+ WhenCondition,
+ true_condition,
)
diff --git a/src/aiogram_dialog/widgets/text/format.py b/src/aiogram_dialog/widgets/text/format.py
index 89e564ce..035e1d17 100644
--- a/src/aiogram_dialog/widgets/text/format.py
+++ b/src/aiogram_dialog/widgets/text/format.py
@@ -1,5 +1,6 @@
from aiogram_dialog.api.protocols import DialogManager
from aiogram_dialog.widgets.common import WhenCondition
+
from .base import Text
diff --git a/src/aiogram_dialog/widgets/text/jinja.py b/src/aiogram_dialog/widgets/text/jinja.py
index abe38781..3a9edc47 100644
--- a/src/aiogram_dialog/widgets/text/jinja.py
+++ b/src/aiogram_dialog/widgets/text/jinja.py
@@ -1,16 +1,17 @@
import warnings
+from collections.abc import Callable, Iterable, Mapping
from typing import (
Any,
Optional,
Union,
)
-from collections.abc import Callable, Iterable, Mapping
from aiogram import Bot, Dispatcher
from jinja2 import BaseLoader, Environment
from aiogram_dialog.api.protocols import DialogManager
from aiogram_dialog.widgets.common import WhenCondition
+
from .base import Text
JINJA_ENV_FIELD = "DialogsJinjaEnvironment"
diff --git a/src/aiogram_dialog/widgets/text/list.py b/src/aiogram_dialog/widgets/text/list.py
index 5dd7458e..f3930f54 100644
--- a/src/aiogram_dialog/widgets/text/list.py
+++ b/src/aiogram_dialog/widgets/text/list.py
@@ -1,16 +1,19 @@
-from typing import Any, Optional
from collections.abc import Sequence
+from typing import Any, Optional
from aiogram_dialog.api.protocols import DialogManager
from aiogram_dialog.widgets.common import (
- BaseScroll, OnPageChangedVariants, WhenCondition,
+ BaseScroll,
+ OnPageChangedVariants,
+ WhenCondition,
)
-from .base import Text
from aiogram_dialog.widgets.common.items import (
- get_items_getter,
ItemsGetterVariant,
+ get_items_getter,
)
+from .base import Text
+
class List(Text, BaseScroll):
def __init__(
diff --git a/src/aiogram_dialog/widgets/text/multi.py b/src/aiogram_dialog/widgets/text/multi.py
index d5efc5ee..d7facd0a 100644
--- a/src/aiogram_dialog/widgets/text/multi.py
+++ b/src/aiogram_dialog/widgets/text/multi.py
@@ -1,10 +1,11 @@
-from typing import Any, Optional, Union
from collections.abc import Callable, Hashable
+from typing import Any, Optional, Union
from magic_filter import MagicFilter
from aiogram_dialog.api.protocols import DialogManager
from aiogram_dialog.widgets.common import WhenCondition
+
from .base import Text
Selector = Callable[[dict, "Case", DialogManager], Hashable]
diff --git a/src/aiogram_dialog/widgets/text/progress.py b/src/aiogram_dialog/widgets/text/progress.py
index cb20ff14..6f492f26 100644
--- a/src/aiogram_dialog/widgets/text/progress.py
+++ b/src/aiogram_dialog/widgets/text/progress.py
@@ -1,5 +1,6 @@
from aiogram_dialog.api.protocols import DialogManager
from aiogram_dialog.widgets.common import WhenCondition
+
from .base import Text
diff --git a/src/aiogram_dialog/widgets/text/scrolling_text.py b/src/aiogram_dialog/widgets/text/scrolling_text.py
index 206fe076..488b9b29 100644
--- a/src/aiogram_dialog/widgets/text/scrolling_text.py
+++ b/src/aiogram_dialog/widgets/text/scrolling_text.py
@@ -1,7 +1,10 @@
from aiogram_dialog.api.protocols import DialogManager
from aiogram_dialog.widgets.common import (
- BaseScroll, OnPageChangedVariants, WhenCondition,
+ BaseScroll,
+ OnPageChangedVariants,
+ WhenCondition,
)
+
from .base import Text
diff --git a/src/aiogram_dialog/widgets/utils.py b/src/aiogram_dialog/widgets/utils.py
index 3ce7e994..16aa047d 100644
--- a/src/aiogram_dialog/widgets/utils.py
+++ b/src/aiogram_dialog/widgets/utils.py
@@ -1,8 +1,9 @@
-from typing import Union
from collections.abc import Callable, Sequence
+from typing import Union
from aiogram_dialog.api.exceptions import InvalidWidgetType
from aiogram_dialog.api.internal import DataGetter
+
from .data.data_context import CompositeGetter, StaticGetter
from .input import BaseInput, CombinedInput, MessageHandlerFunc, MessageInput
from .kbd import Group, Keyboard
diff --git a/src/aiogram_dialog/widgets/widget_event.py b/src/aiogram_dialog/widgets/widget_event.py
index d15cafe9..f3c31da8 100644
--- a/src/aiogram_dialog/widgets/widget_event.py
+++ b/src/aiogram_dialog/widgets/widget_event.py
@@ -1,6 +1,6 @@
from abc import abstractmethod
-from typing import Any, Union
from collections.abc import Callable
+from typing import Any, Union
from aiogram_dialog.api.entities import ChatEvent
from aiogram_dialog.api.protocols import DialogManager
diff --git a/src/aiogram_dialog/window.py b/src/aiogram_dialog/window.py
index d14078a6..618a23eb 100644
--- a/src/aiogram_dialog/window.py
+++ b/src/aiogram_dialog/window.py
@@ -1,11 +1,11 @@
from logging import getLogger
-from typing import Any, cast, Optional
+from typing import Any, Optional, cast
from aiogram.fsm.state import State
from aiogram.types import (
+ UNSET_PARSE_MODE,
CallbackQuery,
Message,
- UNSET_PARSE_MODE,
)
from aiogram.types.base import UNSET_DISABLE_WEB_PAGE_PREVIEW
@@ -17,6 +17,7 @@
NewMessage,
)
from aiogram_dialog.api.internal import Widget, WindowProtocol
+
from .api.entities import Data
from .api.internal.widgets import MarkupFactory
from .api.protocols import DialogManager, DialogProtocol
@@ -25,10 +26,10 @@
from .widgets.kbd import Keyboard
from .widgets.markup.inline_keyboard import InlineKeyboardFactory
from .widgets.utils import (
- ensure_data_getter,
- ensure_widgets,
GetterVariant,
WidgetSrc,
+ ensure_data_getter,
+ ensure_widgets,
)
logger = getLogger(__name__)
From 3d8d3cf164afadba52e9cdd8eebf297c3af0b637 Mon Sep 17 00:00:00 2001
From: chiri <2alivemafia@gmail.com>
Date: Wed, 6 Nov 2024 01:08:49 +0300
Subject: [PATCH 10/29] fix imports
---
example/custom_media_url.py | 10 +++++-----
example/i18n/bot.py | 6 +++++-
example/i18n/i18n_middleware.py | 4 ++--
example/input_media_group.py | 6 +++++-
example/launch_modes.py | 7 ++++++-
example/list_group.py | 15 +++++++++++----
example/loading.py | 8 ++++++--
example/mega/bot.py | 2 +-
example/mega/bot_dialogs/calendar.py | 15 +++++++++++----
example/mega/bot_dialogs/common.py | 1 +
example/mega/bot_dialogs/counter.py | 1 +
example/mega/bot_dialogs/layouts.py | 11 +++++++++--
example/mega/bot_dialogs/main.py | 1 +
example/mega/bot_dialogs/mutltiwidget.py | 1 +
example/mega/bot_dialogs/reply_buttons.py | 8 ++++++--
example/mega/bot_dialogs/scrolls.py | 16 ++++++++++++----
example/mega/bot_dialogs/select.py | 9 +++++++--
example/mega/bot_dialogs/switch.py | 1 +
example/multistack.py | 7 +++++--
example/scrolls.py | 22 ++++++++++++++++------
example/simple.py | 10 +++++++---
example/subdialog.py | 17 +++++++++++++----
example/wizard.py | 6 +++++-
src/aiogram_dialog/widgets/kbd/select.py | 2 +-
24 files changed, 138 insertions(+), 48 deletions(-)
diff --git a/example/custom_media_url.py b/example/custom_media_url.py
index 19b43fde..67acc22b 100644
--- a/example/custom_media_url.py
+++ b/example/custom_media_url.py
@@ -4,17 +4,18 @@
from io import BytesIO
from typing import Union
-
from aiogram import Bot, Dispatcher
from aiogram.filters import CommandStart
from aiogram.fsm.state import State, StatesGroup
from aiogram.types import BufferedInputFile, ContentType, InputFile, Message
from PIL import Image, ImageDraw, ImageFont
-
from aiogram_dialog import (
- Dialog, DialogManager, setup_dialogs,
- StartMode, Window,
+ Dialog,
+ DialogManager,
+ StartMode,
+ Window,
+ setup_dialogs,
)
from aiogram_dialog.api.entities import MediaAttachment
from aiogram_dialog.manager.message_manager import MessageManager
@@ -22,7 +23,6 @@
from aiogram_dialog.widgets.media import StaticMedia
from aiogram_dialog.widgets.text import Const
-
src_dir = os.path.normpath(os.path.join(__file__, os.path.pardir))
API_TOKEN = os.getenv("BOT_TOKEN")
diff --git a/example/i18n/bot.py b/example/i18n/bot.py
index aa908788..949d9445 100644
--- a/example/i18n/bot.py
+++ b/example/i18n/bot.py
@@ -18,7 +18,11 @@
from i18n_middleware import I18nMiddleware
from aiogram_dialog import (
- Dialog, DialogManager, setup_dialogs, StartMode, Window,
+ Dialog,
+ DialogManager,
+ StartMode,
+ Window,
+ setup_dialogs,
)
from aiogram_dialog.widgets.kbd import Button, Cancel, Row
diff --git a/example/i18n/i18n_middleware.py b/example/i18n/i18n_middleware.py
index 20fa32b2..e0cfaf5b 100644
--- a/example/i18n/i18n_middleware.py
+++ b/example/i18n/i18n_middleware.py
@@ -1,5 +1,5 @@
-from typing import Any, Union
from collections.abc import Awaitable, Callable
+from typing import Any, Union
from aiogram.dispatcher.middlewares.base import BaseMiddleware
from aiogram.types import CallbackQuery, Message
@@ -24,7 +24,7 @@ async def __call__(
Awaitable[Any],
],
event: Union[Message, CallbackQuery],
- data: Dict[str, Any],
+ data: dict[str, Any],
) -> Any:
# some language/locale retrieving logic
if event.from_user:
diff --git a/example/input_media_group.py b/example/input_media_group.py
index e54efac5..c5e1939a 100644
--- a/example/input_media_group.py
+++ b/example/input_media_group.py
@@ -10,7 +10,11 @@
from aiogram.types import CallbackQuery, Message
from aiogram_dialog import (
- Dialog, DialogManager, setup_dialogs, StartMode, Window,
+ Dialog,
+ DialogManager,
+ StartMode,
+ Window,
+ setup_dialogs,
)
from aiogram_dialog.api.entities import MediaAttachment, MediaId
from aiogram_dialog.widgets.common import ManagedScroll
diff --git a/example/launch_modes.py b/example/launch_modes.py
index f68f63f4..78aab3ec 100644
--- a/example/launch_modes.py
+++ b/example/launch_modes.py
@@ -9,7 +9,12 @@
from aiogram.types import Message
from aiogram_dialog import (
- Dialog, DialogManager, LaunchMode, setup_dialogs, StartMode, Window,
+ Dialog,
+ DialogManager,
+ LaunchMode,
+ StartMode,
+ Window,
+ setup_dialogs,
)
from aiogram_dialog.widgets.kbd import Cancel, Row, Start
from aiogram_dialog.widgets.text import Const, Format
diff --git a/example/list_group.py b/example/list_group.py
index a66a18ba..37df5f07 100644
--- a/example/list_group.py
+++ b/example/list_group.py
@@ -9,13 +9,20 @@
from aiogram.types import Message
from aiogram_dialog import (
- Dialog, DialogManager, LaunchMode,
- setup_dialogs, StartMode, SubManager,
+ Dialog,
+ DialogManager,
+ LaunchMode,
+ StartMode,
+ SubManager,
Window,
+ setup_dialogs,
)
from aiogram_dialog.widgets.kbd import (
- Checkbox, ListGroup,
- ManagedCheckbox, Radio, Row,
+ Checkbox,
+ ListGroup,
+ ManagedCheckbox,
+ Radio,
+ Row,
)
from aiogram_dialog.widgets.text import Const, Format
diff --git a/example/loading.py b/example/loading.py
index fd810716..f8b43e8f 100644
--- a/example/loading.py
+++ b/example/loading.py
@@ -9,8 +9,12 @@
from aiogram.types import CallbackQuery, Message
from aiogram_dialog import (
- BaseDialogManager, Dialog, DialogManager,
- setup_dialogs, StartMode, Window,
+ BaseDialogManager,
+ Dialog,
+ DialogManager,
+ StartMode,
+ Window,
+ setup_dialogs,
)
from aiogram_dialog.widgets.kbd import Button
from aiogram_dialog.widgets.text import Const, Multi, Progress
diff --git a/example/mega/bot.py b/example/mega/bot.py
index 11d43bb7..c73ed60f 100644
--- a/example/mega/bot.py
+++ b/example/mega/bot.py
@@ -18,7 +18,7 @@
from bot_dialogs.select import selects_dialog
from bot_dialogs.switch import switch_dialog
-from aiogram_dialog import DialogManager, setup_dialogs, ShowMode, StartMode
+from aiogram_dialog import DialogManager, ShowMode, StartMode, setup_dialogs
from aiogram_dialog.api.exceptions import UnknownIntent
diff --git a/example/mega/bot_dialogs/calendar.py b/example/mega/bot_dialogs/calendar.py
index 4f1bbe14..b1e8a113 100644
--- a/example/mega/bot_dialogs/calendar.py
+++ b/example/mega/bot_dialogs/calendar.py
@@ -5,14 +5,21 @@
from aiogram_dialog import ChatEvent, Dialog, DialogManager, Window
from aiogram_dialog.widgets.kbd import (
- Calendar, CalendarScope, ManagedCalendar, SwitchTo,
+ Calendar,
+ CalendarScope,
+ ManagedCalendar,
+ SwitchTo,
)
from aiogram_dialog.widgets.kbd.calendar_kbd import (
- CalendarDaysView, CalendarMonthView,
- CalendarScopeView, CalendarYearsView,
- DATE_TEXT, TODAY_TEXT,
+ DATE_TEXT,
+ TODAY_TEXT,
+ CalendarDaysView,
+ CalendarMonthView,
+ CalendarScopeView,
+ CalendarYearsView,
)
from aiogram_dialog.widgets.text import Const, Format, Text
+
from . import states
from .common import MAIN_MENU_BUTTON
diff --git a/example/mega/bot_dialogs/common.py b/example/mega/bot_dialogs/common.py
index 89718bdd..3cf5ab2e 100644
--- a/example/mega/bot_dialogs/common.py
+++ b/example/mega/bot_dialogs/common.py
@@ -1,5 +1,6 @@
from aiogram_dialog.widgets.kbd import Start
from aiogram_dialog.widgets.text import Const
+
from . import states
MAIN_MENU_BUTTON = Start(
diff --git a/example/mega/bot_dialogs/counter.py b/example/mega/bot_dialogs/counter.py
index 445d8066..a5efad82 100644
--- a/example/mega/bot_dialogs/counter.py
+++ b/example/mega/bot_dialogs/counter.py
@@ -3,6 +3,7 @@
from aiogram_dialog import Dialog, DialogManager, Window
from aiogram_dialog.widgets.kbd import Counter, ManagedCounter
from aiogram_dialog.widgets.text import Const, Progress
+
from . import states
from .common import MAIN_MENU_BUTTON
diff --git a/example/mega/bot_dialogs/layouts.py b/example/mega/bot_dialogs/layouts.py
index 6e7f7082..a56e04f2 100644
--- a/example/mega/bot_dialogs/layouts.py
+++ b/example/mega/bot_dialogs/layouts.py
@@ -1,10 +1,17 @@
from aiogram_dialog import (
- Dialog, Window,
+ Dialog,
+ Window,
)
from aiogram_dialog.widgets.kbd import (
- Button, Column, Group, Row, Select, SwitchTo,
+ Button,
+ Column,
+ Group,
+ Row,
+ Select,
+ SwitchTo,
)
from aiogram_dialog.widgets.text import Const, Format
+
from . import states
from .common import MAIN_MENU_BUTTON
diff --git a/example/mega/bot_dialogs/main.py b/example/mega/bot_dialogs/main.py
index b6a3c8dd..7305ddf5 100644
--- a/example/mega/bot_dialogs/main.py
+++ b/example/mega/bot_dialogs/main.py
@@ -2,6 +2,7 @@
from aiogram_dialog.about import about_aiogram_dialog_button
from aiogram_dialog.widgets.kbd import Start
from aiogram_dialog.widgets.text import Const
+
from . import states
main_dialog = Dialog(
diff --git a/example/mega/bot_dialogs/mutltiwidget.py b/example/mega/bot_dialogs/mutltiwidget.py
index c9f07b03..3bc0f2a1 100644
--- a/example/mega/bot_dialogs/mutltiwidget.py
+++ b/example/mega/bot_dialogs/mutltiwidget.py
@@ -1,6 +1,7 @@
from aiogram_dialog import Dialog, Window
from aiogram_dialog.widgets.kbd import Checkbox, Counter, Multiselect, Radio
from aiogram_dialog.widgets.text import Const, Format
+
from . import states
from .common import MAIN_MENU_BUTTON
diff --git a/example/mega/bot_dialogs/reply_buttons.py b/example/mega/bot_dialogs/reply_buttons.py
index 1d4a341c..a9024da1 100644
--- a/example/mega/bot_dialogs/reply_buttons.py
+++ b/example/mega/bot_dialogs/reply_buttons.py
@@ -1,10 +1,14 @@
from aiogram_dialog import Dialog, Window
from aiogram_dialog.widgets.kbd import (
- Checkbox, Radio, RequestContact,
- RequestLocation, Row,
+ Checkbox,
+ Radio,
+ RequestContact,
+ RequestLocation,
+ Row,
)
from aiogram_dialog.widgets.markup.reply_keyboard import ReplyKeyboardFactory
from aiogram_dialog.widgets.text import Const, Format
+
from . import states
from .common import MAIN_MENU_BUTTON
diff --git a/example/mega/bot_dialogs/scrolls.py b/example/mega/bot_dialogs/scrolls.py
index 3e8c264a..cb474a30 100644
--- a/example/mega/bot_dialogs/scrolls.py
+++ b/example/mega/bot_dialogs/scrolls.py
@@ -4,13 +4,21 @@
from aiogram_dialog import Dialog, DialogManager, Window
from aiogram_dialog.widgets.common import sync_scroll
from aiogram_dialog.widgets.kbd import (
- CurrentPage, FirstPage, LastPage,
- Multiselect, NextPage, NumberedPager,
- PrevPage, Row, ScrollingGroup,
- StubScroll, SwitchTo,
+ CurrentPage,
+ FirstPage,
+ LastPage,
+ Multiselect,
+ NextPage,
+ NumberedPager,
+ PrevPage,
+ Row,
+ ScrollingGroup,
+ StubScroll,
+ SwitchTo,
)
from aiogram_dialog.widgets.media import StaticMedia
from aiogram_dialog.widgets.text import Const, Format, List, ScrollingText
+
from . import states
from .common import MAIN_MENU_BUTTON
diff --git a/example/mega/bot_dialogs/select.py b/example/mega/bot_dialogs/select.py
index 169e537f..438fef8e 100644
--- a/example/mega/bot_dialogs/select.py
+++ b/example/mega/bot_dialogs/select.py
@@ -5,10 +5,15 @@
from aiogram_dialog import Dialog, DialogManager, Window
from aiogram_dialog.widgets.kbd import (
- Column, Multiselect, Radio,
- Select, SwitchTo, Toggle,
+ Column,
+ Multiselect,
+ Radio,
+ Select,
+ SwitchTo,
+ Toggle,
)
from aiogram_dialog.widgets.text import Const, Format, List
+
from . import states
from .common import MAIN_MENU_BUTTON
diff --git a/example/mega/bot_dialogs/switch.py b/example/mega/bot_dialogs/switch.py
index faf3a4d0..4848e61a 100644
--- a/example/mega/bot_dialogs/switch.py
+++ b/example/mega/bot_dialogs/switch.py
@@ -3,6 +3,7 @@
from aiogram_dialog import Dialog, DialogManager, Window
from aiogram_dialog.widgets.kbd import Back, Checkbox, Next, Radio, Row
from aiogram_dialog.widgets.text import Case, Const, Format
+
from . import states
from .common import MAIN_MENU_BUTTON
diff --git a/example/multistack.py b/example/multistack.py
index 14e70ca3..cb780e4d 100644
--- a/example/multistack.py
+++ b/example/multistack.py
@@ -11,8 +11,11 @@
from aiogram.types import CallbackQuery, Message
from aiogram_dialog import (
- Dialog, DialogManager,
- setup_dialogs, StartMode, Window,
+ Dialog,
+ DialogManager,
+ StartMode,
+ Window,
+ setup_dialogs,
)
from aiogram_dialog.widgets.input import MessageInput
from aiogram_dialog.widgets.kbd import Button, Cancel, Multiselect, Start
diff --git a/example/scrolls.py b/example/scrolls.py
index 349eacf6..70eec81b 100644
--- a/example/scrolls.py
+++ b/example/scrolls.py
@@ -11,14 +11,24 @@
from aiogram.types import Message
from aiogram_dialog import (
- Dialog, DialogManager,
- setup_dialogs, StartMode, Window,
+ Dialog,
+ DialogManager,
+ StartMode,
+ Window,
+ setup_dialogs,
)
from aiogram_dialog.widgets.kbd import (
- CurrentPage, FirstPage, LastPage,
- Multiselect, NextPage, NumberedPager,
- PrevPage, Row, ScrollingGroup,
- StubScroll, SwitchTo,
+ CurrentPage,
+ FirstPage,
+ LastPage,
+ Multiselect,
+ NextPage,
+ NumberedPager,
+ PrevPage,
+ Row,
+ ScrollingGroup,
+ StubScroll,
+ SwitchTo,
)
from aiogram_dialog.widgets.text import Const, Format, List, ScrollingText
diff --git a/example/simple.py b/example/simple.py
index 7a939a61..ae6826d5 100644
--- a/example/simple.py
+++ b/example/simple.py
@@ -11,9 +11,13 @@
from redis.asyncio.client import Redis
from aiogram_dialog import (
- ChatEvent, Dialog, DialogManager,
- setup_dialogs, ShowMode,
- StartMode, Window,
+ ChatEvent,
+ Dialog,
+ DialogManager,
+ ShowMode,
+ StartMode,
+ Window,
+ setup_dialogs,
)
from aiogram_dialog.api.exceptions import UnknownIntent, UnknownState
from aiogram_dialog.widgets.input import MessageInput
diff --git a/example/subdialog.py b/example/subdialog.py
index cb1a3102..c169277e 100644
--- a/example/subdialog.py
+++ b/example/subdialog.py
@@ -10,14 +10,23 @@
from aiogram.types import CallbackQuery, Message
from aiogram_dialog import (
- Data, Dialog, DialogManager,
- setup_dialogs, StartMode, Window,
+ Data,
+ Dialog,
+ DialogManager,
+ StartMode,
+ Window,
+ setup_dialogs,
)
from aiogram_dialog.tools import render_preview, render_transitions
from aiogram_dialog.widgets.input import MessageInput
from aiogram_dialog.widgets.kbd import (
- Back, Button, Cancel,
- Group, Next, Row, Start,
+ Back,
+ Button,
+ Cancel,
+ Group,
+ Next,
+ Row,
+ Start,
)
from aiogram_dialog.widgets.text import Const, Format, Multi
diff --git a/example/wizard.py b/example/wizard.py
index 8cea2a17..b1017ea0 100644
--- a/example/wizard.py
+++ b/example/wizard.py
@@ -8,7 +8,11 @@
from aiogram.types import Message
from aiogram_dialog import (
- Dialog, DialogManager, setup_dialogs, StartMode, Window,
+ Dialog,
+ DialogManager,
+ StartMode,
+ Window,
+ setup_dialogs,
)
from aiogram_dialog.widgets.input import TextInput
from aiogram_dialog.widgets.kbd import Checkbox, Next, SwitchTo
diff --git a/src/aiogram_dialog/widgets/kbd/select.py b/src/aiogram_dialog/widgets/kbd/select.py
index 320df9d9..2fe2c70d 100644
--- a/src/aiogram_dialog/widgets/kbd/select.py
+++ b/src/aiogram_dialog/widgets/kbd/select.py
@@ -387,7 +387,7 @@ async def set_checked(
if not checked and len(data) > self.min_selected:
data.remove(item_id_str)
changed = True
- elif checked and self.max_selected == 0 or self.max_selected > len(data):
+ elif checked and self.max_selected == 0 or self.max_selected > len(data): # noqa: E501
data.append(item_id_str)
changed = True
if changed:
From c150675fe8cbf6af813ebf4c4dadadd9d65f8e23 Mon Sep 17 00:00:00 2001
From: chiri <2alivemafia@gmail.com>
Date: Wed, 6 Nov 2024 11:09:54 +0300
Subject: [PATCH 11/29] drop flake8, add ruff, add uv for workflows
---
.flake8 | 41 ----------
.github/workflows/setup.yml | 13 ++--
.ruff.toml | 74 +++++++++++++++++++
example/input_media_group.py | 4 +-
example/list_group.py | 8 +-
example/loading.py | 4 +-
example/mega/bot.py | 2 +-
example/mega/bot_dialogs/select.py | 16 ++--
example/multistack.py | 2 +-
example/scrolls.py | 2 +-
example/simple.py | 2 +-
example/subdialog.py | 2 +-
example/wizard.py | 2 +-
requirements_dev.txt | 14 +---
.../context/intent_middleware.py | 11 ++-
src/aiogram_dialog/context/media_storage.py | 2 +-
src/aiogram_dialog/context/storage.py | 8 +-
src/aiogram_dialog/dialog.py | 3 +-
src/aiogram_dialog/manager/manager.py | 8 +-
src/aiogram_dialog/manager/message_manager.py | 7 +-
src/aiogram_dialog/manager/updater.py | 2 +-
.../test_tools/memory_storage.py | 8 +-
.../test_tools/mock_message_manager.py | 8 +-
src/aiogram_dialog/tools/preview.py | 32 ++++----
src/aiogram_dialog/utils.py | 15 ++--
src/aiogram_dialog/widgets/common/when.py | 6 +-
.../widgets/kbd/calendar_kbd.py | 2 +-
src/aiogram_dialog/widgets/kbd/counter.py | 2 +-
src/aiogram_dialog/widgets/kbd/group.py | 4 +-
src/aiogram_dialog/widgets/kbd/list_group.py | 2 +-
src/aiogram_dialog/widgets/kbd/select.py | 12 +--
src/aiogram_dialog/widgets/media/static.py | 2 +-
src/aiogram_dialog/window.py | 5 +-
tests/test_click.py | 6 +-
tests/test_create.py | 2 +-
tests/test_events.py | 6 +-
tests/test_group.py | 11 ++-
tests/test_nested_transitions.py | 6 +-
tests/test_transitions.py | 6 +-
tests/widgets/kbd/test_group.py | 6 +-
tests/widgets/media/test_media_message.py | 2 +-
41 files changed, 208 insertions(+), 162 deletions(-)
delete mode 100644 .flake8
create mode 100644 .ruff.toml
diff --git a/.flake8 b/.flake8
deleted file mode 100644
index 8a4bef99..00000000
--- a/.flake8
+++ /dev/null
@@ -1,41 +0,0 @@
-[flake8]
-count=True
-statistics=True
-show-source=True
-
-max-line-length=79
-import-order-style=smarkets
-application-import-names=aiogram_dialog
-exclude=
- .venv,
- docs,
- benchmarks
-docstring-convention=pep257
-ignore=
- # A002 argument "object" is shadowing a python builtin
- A002,
- # A003 class attribute "id" is shadowing a python builtin
- A003,
- # A005 A module is shadowing a Python builtin module
- A005,
- # D100 Missing docstring in public module
- D100,
- # D101 Missing docstring in public class
- D101,
- # D102 Missing docstring in public method
- D102,
- # D103 Missing docstring in public function
- D103,
- # D104 Missing docstring in public package
- D104,
- # D105 Missing docstring in magic method
- D105,
- # D107 Missing docstring in __init__
- D107,
- # W504 line break after binary operator
- W504,
-max-cognitive-complexity=10
-max-complexity=10
-per-file-ignores=
- tests/**:D1,E800,A003
- **/__init__.py:F401
diff --git a/.github/workflows/setup.yml b/.github/workflows/setup.yml
index f9aeaeb7..41847be8 100644
--- a/.github/workflows/setup.yml
+++ b/.github/workflows/setup.yml
@@ -33,15 +33,16 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
+ - name: Install uv
+ uses: astral-sh/setup-uv@v3
+
- name: Install dependencies
run: |
- python -m pip install --upgrade pip
- pip install . -r requirements_dev.txt
- pip install diagrams
+ uv pip install . -r requirements_dev.txt
+ uv pip install diagrams
- - name: Run flake8
- run: |
- python -m flake8 src/aiogram_dialog tests example
+ - name: Run Ruff
+ run: ruff check src/aiogram_dialog tests example
- name: Run tests
run: |
diff --git a/.ruff.toml b/.ruff.toml
new file mode 100644
index 00000000..6d1b7998
--- /dev/null
+++ b/.ruff.toml
@@ -0,0 +1,74 @@
+line-length = 79
+target-version="py39"
+src = ["src"]
+
+include = ["src/**.py", "tests/**.py", "example/**.py"]
+exclude = ["docs"]
+
+lint.select = ["ALL"]
+lint.ignore = [
+ "ARG",
+ "ANN",
+ "D",
+ "DTZ",
+ "TD",
+ "EM101",
+ "EM102",
+ "PT001",
+ "PT023",
+ "SIM108",
+ "SIM114",
+ "TRY003",
+ "TCH003",
+ "PLW2901",
+ "RET505",
+ "PLR0913",
+ "UP038",
+ "TCH001",
+ "SIM103",
+ "ISC003",
+ "A002",
+ "FA100",
+ "TRY400",
+ "FBT001",
+ "FBT002",
+ "S311",
+ "N818",
+ "B904",
+ "FIX002",
+ "RUF012",
+ "TCH002",
+ "TRY201",
+ "ISC002",
+ "ASYNC230",
+ "UP007",
+ "N804",
+ "B008",
+ "BLE001",
+ "RUF009",
+ "PYI034",
+]
+
+[lint.per-file-ignores]
+"src/aiogram_dialog/tools/**" = [
+ "S101",
+ "SLF001",
+ "PTH",
+]
+"src/aiogram_dialog/test_tools/**"= [
+ "S101",
+ "PTH"
+]
+"tests/**" = [
+ "TID252",
+ "PLR2004",
+ "S101",
+ "INP001",
+ "FBT003",
+]
+"example/**" = [
+ "INP001",
+ "ERA001",
+ "RUF001",
+ "PTH",
+]
\ No newline at end of file
diff --git a/example/input_media_group.py b/example/input_media_group.py
index c5e1939a..ba608e7b 100644
--- a/example/input_media_group.py
+++ b/example/input_media_group.py
@@ -61,7 +61,7 @@ async def getter(dialog_manager: DialogManager, **kwargs) -> dict:
)
else:
media = MediaAttachment(
- url="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/Image_not_available.png/800px-Image_not_available.png?20210219185637", # noqa: E501
+ url="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/Image_not_available.png/800px-Image_not_available.png?20210219185637",
type=ContentType.PHOTO,
)
return {
@@ -109,5 +109,5 @@ async def main():
await dp.start_polling(bot)
-if __name__ == '__main__':
+if __name__ == "__main__":
asyncio.run(main())
diff --git a/example/list_group.py b/example/list_group.py
index 37df5f07..7104f8a1 100644
--- a/example/list_group.py
+++ b/example/list_group.py
@@ -67,8 +67,8 @@ async def data_getter(*args, **kwargs):
item_id_getter=str,
items=["black", "white"],
# Alternatives:
- # items=F["data"]["colors"], # noqa: E800
- # items=lambda d: d["data"]["colors"], # noqa: E800
+ # items=F["data"]["colors"],
+ # items=lambda d: d["data"]["colors"],
when=when_checked,
),
),
@@ -76,8 +76,8 @@ async def data_getter(*args, **kwargs):
item_id_getter=str,
items=["apple", "orange", "pear"],
# Alternatives:
- # items=F["fruits"], # noqa: E800
- # items=lambda d: d["fruits"], # noqa: E800
+ # items=F["fruits"],
+ # items=lambda d: d["fruits"],
),
state=DialogSG.greeting,
getter=data_getter,
diff --git a/example/loading.py b/example/loading.py
index f8b43e8f..baf0359b 100644
--- a/example/loading.py
+++ b/example/loading.py
@@ -57,7 +57,7 @@ async def start_bg(
manager: DialogManager,
):
await manager.start(Bg.progress)
- asyncio.create_task(background(callback, manager.bg()))
+ asyncio.create_task(background(callback, manager.bg())) # noqa: RUF006
async def background(callback: CallbackQuery, manager: BaseDialogManager):
@@ -99,5 +99,5 @@ async def main():
await dp.start_polling(bot)
-if __name__ == '__main__':
+if __name__ == "__main__":
asyncio.run(main())
diff --git a/example/mega/bot.py b/example/mega/bot.py
index c73ed60f..851342d3 100644
--- a/example/mega/bot.py
+++ b/example/mega/bot.py
@@ -40,7 +40,7 @@ async def on_unknown_intent(event: ErrorEvent, dialog_manager: DialogManager):
"Redirecting to main menu.",
)
if event.update.callback_query.message:
- try:
+ try: # noqa: SIM105
await event.update.callback_query.message.delete()
except TelegramBadRequest:
pass # whatever
diff --git a/example/mega/bot_dialogs/select.py b/example/mega/bot_dialogs/select.py
index 438fef8e..f85767e2 100644
--- a/example/mega/bot_dialogs/select.py
+++ b/example/mega/bot_dialogs/select.py
@@ -94,8 +94,8 @@ async def on_item_selected(
field=Format("+ {item.emoji} {item.name} - {item.id}"),
items=FRUITS_KEY,
# Alternatives:
- # items=lambda d: d[OTHER_KEY][FRUITS_KEY], # noqa: E800
- # items=F[OTHER_KEY][FRUITS_KEY], # noqa: E800
+ # items=lambda d: d[OTHER_KEY][FRUITS_KEY],
+ # items=F[OTHER_KEY][FRUITS_KEY],
),
Column(
Select(
@@ -103,8 +103,8 @@ async def on_item_selected(
id="sel",
items=FRUITS_KEY,
# Alternatives:
- # items=lambda d: d[OTHER_KEY][FRUITS_KEY], # noqa: E800
- # items=F[OTHER_KEY][FRUITS_KEY], # noqa: E800
+ # items=lambda d: d[OTHER_KEY][FRUITS_KEY],
+ # items=F[OTHER_KEY][FRUITS_KEY],
item_id_getter=fruit_id_getter,
on_click=on_item_selected,
),
@@ -123,8 +123,8 @@ async def on_item_selected(
id="radio",
items=FRUITS_KEY,
# Alternatives:
- # items=lambda d: d[OTHER_KEY][FRUITS_KEY], # noqa: E800
- # items=F[OTHER_KEY][FRUITS_KEY], # noqa: E800
+ # items=lambda d: d[OTHER_KEY][FRUITS_KEY],
+ # items=F[OTHER_KEY][FRUITS_KEY],
item_id_getter=fruit_id_getter,
),
),
@@ -143,8 +143,8 @@ async def on_item_selected(
id="multi",
items=FRUITS_KEY,
# Alternatives:
- # items=lambda d: d[OTHER_KEY][FRUITS_KEY], # noqa: E800
- # items=F[OTHER_KEY][FRUITS_KEY], # noqa: E800
+ # items=lambda d: d[OTHER_KEY][FRUITS_KEY],
+ # items=F[OTHER_KEY][FRUITS_KEY],
item_id_getter=fruit_id_getter,
),
),
diff --git a/example/multistack.py b/example/multistack.py
index cb780e4d..de1e5ca2 100644
--- a/example/multistack.py
+++ b/example/multistack.py
@@ -112,5 +112,5 @@ async def main():
await dp.start_polling(bot)
-if __name__ == '__main__':
+if __name__ == "__main__":
asyncio.run(main())
diff --git a/example/scrolls.py b/example/scrolls.py
index 70eec81b..d6e7bf95 100644
--- a/example/scrolls.py
+++ b/example/scrolls.py
@@ -233,5 +233,5 @@ async def main():
await dp.start_polling(bot)
-if __name__ == '__main__':
+if __name__ == "__main__":
asyncio.run(main())
diff --git a/example/simple.py b/example/simple.py
index ae6826d5..13bd9c41 100644
--- a/example/simple.py
+++ b/example/simple.py
@@ -176,5 +176,5 @@ async def main():
await dp.start_polling(bot)
-if __name__ == '__main__':
+if __name__ == "__main__":
asyncio.run(main())
diff --git a/example/subdialog.py b/example/subdialog.py
index c169277e..ac8cab21 100644
--- a/example/subdialog.py
+++ b/example/subdialog.py
@@ -165,5 +165,5 @@ async def main():
await dp.start_polling(bot)
-if __name__ == '__main__':
+if __name__ == "__main__":
asyncio.run(main())
diff --git a/example/wizard.py b/example/wizard.py
index b1017ea0..47e606dc 100644
--- a/example/wizard.py
+++ b/example/wizard.py
@@ -127,5 +127,5 @@ async def main():
await dp.start_polling(bot)
-if __name__ == '__main__':
+if __name__ == "__main__":
asyncio.run(main())
diff --git a/requirements_dev.txt b/requirements_dev.txt
index 07c80a1e..543ae4f4 100644
--- a/requirements_dev.txt
+++ b/requirements_dev.txt
@@ -1,17 +1,5 @@
vulture
-flake8==7.*
-flake8-blind-except
-flake8-bugbear
-flake8-builtins
-flake8-cognitive-complexity
-flake8-comprehensions
-flake8-docstrings
-flake8-eradicate
-flake8-import-order
-flake8-mutable
-flake8-polyfill
-flake8-print
-
+ruff==0.7.2
pytest
pytest-asyncio
pytest-repeat
\ No newline at end of file
diff --git a/src/aiogram_dialog/context/intent_middleware.py b/src/aiogram_dialog/context/intent_middleware.py
index 069c9ff5..34de801d 100644
--- a/src/aiogram_dialog/context/intent_middleware.py
+++ b/src/aiogram_dialog/context/intent_middleware.py
@@ -129,6 +129,7 @@ def event_context_from_error(event: ErrorEvent) -> EventContext:
return event_context_from_chat_join(event.update.chat_join_request)
elif event.update.callback_query:
return event_context_from_callback(event.update.callback_query)
+ raise ValueError("Unsupported event type in ErrorEvent.update")
class InaccessibleBusinessMessage(InaccessibleMessage):
@@ -150,7 +151,7 @@ def __init__(
def storage_proxy(
self, event_context: EventContext, fsm_storage: BaseStorage,
) -> StorageProxy:
- proxy = StorageProxy(
+ return StorageProxy(
bot=event_context.bot,
storage=fsm_storage,
events_isolation=self.events_isolation,
@@ -160,7 +161,6 @@ def storage_proxy(
thread_id=event_context.thread_id,
business_connection_id=event_context.business_connection_id,
)
- return proxy
def _check_outdated(self, intent_id: str, stack: Stack):
"""Check if intent id is outdated for stack."""
@@ -186,8 +186,7 @@ async def _load_stack(
) -> Optional[Stack]:
if stack_id is None:
raise InvalidStackIdError("Both stack id and intent id are None")
- stack = await proxy.load_stack(stack_id)
- return stack
+ return await proxy.load_stack(stack_id)
async def _load_context_by_stack(
self,
@@ -209,7 +208,7 @@ async def _load_context_by_stack(
else:
try:
context = await proxy.load_context(stack.last_intent_id())
- except: # noqa: B001,B901,E722
+ except:
await proxy.unlock()
raise
@@ -244,7 +243,7 @@ async def _load_context_by_intent(
return
try:
self._check_outdated(intent_id, stack)
- except: # noqa: B001,B901,E722
+ except:
await proxy.unlock()
raise
diff --git a/src/aiogram_dialog/context/media_storage.py b/src/aiogram_dialog/context/media_storage.py
index 9a972d2f..6ba290da 100644
--- a/src/aiogram_dialog/context/media_storage.py
+++ b/src/aiogram_dialog/context/media_storage.py
@@ -29,5 +29,5 @@ async def save_media_id(
media_id: MediaId,
) -> None:
if not path and not url:
- return None
+ return
self.cache[(path, url, type)] = media_id
diff --git a/src/aiogram_dialog/context/storage.py b/src/aiogram_dialog/context/storage.py
index bd99102a..e1c22fd6 100644
--- a/src/aiogram_dialog/context/storage.py
+++ b/src/aiogram_dialog/context/storage.py
@@ -142,9 +142,11 @@ def _fixed_stack_id(self, stack_id: str) -> str:
if stack_id != DEFAULT_STACK_ID:
return stack_id
# private chat has chat_id=user_id and no business connection
- if self.user_id in (None, self.chat_id):
- if self.business_connection_id is None:
- return stack_id
+ if (
+ self.user_id in (None, self.chat_id) and
+ self.business_connection_id is None
+ ):
+ return stack_id
return f"<{self.user_id}>"
def _stack_key(self, stack_id: str) -> StorageKey:
diff --git a/src/aiogram_dialog/dialog.py b/src/aiogram_dialog/dialog.py
index c9571c7e..6b2ea5dc 100644
--- a/src/aiogram_dialog/dialog.py
+++ b/src/aiogram_dialog/dialog.py
@@ -120,8 +120,7 @@ async def load_data(
async def render(self, manager: DialogManager) -> NewMessage:
logger.debug("Dialog render (%s)", self)
window = await self._current_window(manager)
- new_message = await window.render(self, manager)
- return new_message
+ return await window.render(self, manager)
async def _message_handler(
self, message: Message, dialog_manager: DialogManager,
diff --git a/src/aiogram_dialog/manager/manager.py b/src/aiogram_dialog/manager/manager.py
index 86837b03..680ef54e 100644
--- a/src/aiogram_dialog/manager/manager.py
+++ b/src/aiogram_dialog/manager/manager.py
@@ -207,9 +207,9 @@ async def done(
async def answer_callback(self) -> None:
if not isinstance(self.event, CallbackQuery):
- return
+ return None
if self.is_event_simulated():
- return
+ return None
return await self.message_manager.answer_callback(
bot=self._data["bot"],
callback_query=self.event,
@@ -308,7 +308,7 @@ async def _process_launch_mode(
):
if new_dialog.launch_mode in (LaunchMode.EXCLUSIVE, LaunchMode.ROOT):
await self.reset_stack(remove_keyboard=False)
- if new_dialog.launch_mode is LaunchMode.SINGLE_TOP:
+ if new_dialog.launch_mode is LaunchMode.SINGLE_TOP: # noqa: SIM102
if new_dialog is old_dialog:
await self.storage().remove_context(self.current_stack().pop())
self._data[CONTEXT_KEY] = None
@@ -466,7 +466,7 @@ def _save_last_message(self, message: OldMessage):
stack.last_media_unique_id = message.media_uniq_id
stack.last_reply_keyboard = message.has_reply_keyboard
- def _calc_show_mode(self) -> ShowMode:
+ def _calc_show_mode(self) -> ShowMode: # noqa: PLR0911
if self.show_mode is not ShowMode.AUTO:
return self.show_mode
if self.middleware_data["event_chat"].type != ChatType.PRIVATE:
diff --git a/src/aiogram_dialog/manager/message_manager.py b/src/aiogram_dialog/manager/message_manager.py
index d3d76a9f..b6d8db72 100644
--- a/src/aiogram_dialog/manager/message_manager.py
+++ b/src/aiogram_dialog/manager/message_manager.py
@@ -200,7 +200,7 @@ async def remove_kbd(
old_message: Optional[OldMessage],
) -> Optional[Message]:
if show_mode is ShowMode.NO_UPDATE:
- return
+ return None
if show_mode is ShowMode.DELETE_AND_SEND and old_message:
return await self.remove_message_safe(bot, old_message, None)
return await self._remove_kbd(bot, old_message, None)
@@ -214,6 +214,7 @@ async def _remove_kbd(
if self.had_reply_keyboard(old_message):
if not self.need_reply_keyboard(new_message):
return await self.remove_reply_kbd(bot, old_message)
+ return None
else:
return await self.remove_inline_kbd(bot, old_message)
@@ -221,7 +222,7 @@ async def remove_inline_kbd(
self, bot: Bot, old_message: Optional[OldMessage],
) -> Optional[Message]:
if not old_message:
- return
+ return None
logger.debug("remove_inline_kbd in %s", old_message.chat)
try:
return await bot.edit_message_reply_markup(
@@ -243,7 +244,7 @@ async def remove_reply_kbd(
self, bot: Bot, old_message: Optional[OldMessage],
) -> Optional[Message]:
if not old_message:
- return
+ return None
logger.debug("remove_reply_kbd in %s", old_message.chat)
return await self.send_text(
bot=bot,
diff --git a/src/aiogram_dialog/manager/updater.py b/src/aiogram_dialog/manager/updater.py
index df8926f7..fa44ecad 100644
--- a/src/aiogram_dialog/manager/updater.py
+++ b/src/aiogram_dialog/manager/updater.py
@@ -16,7 +16,7 @@ def __init__(self, dp: Router):
async def notify(self, bot: Bot, update: DialogUpdate) -> None:
def callback():
- asyncio.create_task(
+ asyncio.create_task( # noqa: RUF006
self._process_update(bot, update),
)
diff --git a/src/aiogram_dialog/test_tools/memory_storage.py b/src/aiogram_dialog/test_tools/memory_storage.py
index de2ecad3..d0ffba70 100644
--- a/src/aiogram_dialog/test_tools/memory_storage.py
+++ b/src/aiogram_dialog/test_tools/memory_storage.py
@@ -1,7 +1,7 @@
import json
from collections import defaultdict
from dataclasses import dataclass
-from typing import Any, Dict, Optional, Union
+from typing import Any, Optional, Union
from aiogram.fsm.state import State
from aiogram.fsm.storage.base import BaseStorage, StorageKey
@@ -16,7 +16,7 @@ class MemoryStorageRecord:
class JsonMemoryStorage(BaseStorage):
- storage: Dict[StorageKey, MemoryStorageRecord]
+ storage: dict[StorageKey, MemoryStorageRecord]
def __init__(self) -> None:
self.storage = defaultdict(MemoryStorageRecord)
@@ -36,8 +36,8 @@ async def set_state(
async def get_state(self, key: StorageKey) -> Optional[str]:
return self.storage[key].state
- async def set_data(self, key: StorageKey, data: Dict[str, Any]) -> None:
+ async def set_data(self, key: StorageKey, data: dict[str, Any]) -> None:
self.storage[key].data = json.dumps(data)
- async def get_data(self, key: StorageKey) -> Dict[str, Any]:
+ async def get_data(self, key: StorageKey) -> dict[str, Any]:
return json.loads(self.storage[key].data)
diff --git a/src/aiogram_dialog/test_tools/mock_message_manager.py b/src/aiogram_dialog/test_tools/mock_message_manager.py
index 2fd2444e..6c5fbf36 100644
--- a/src/aiogram_dialog/test_tools/mock_message_manager.py
+++ b/src/aiogram_dialog/test_tools/mock_message_manager.py
@@ -1,6 +1,6 @@
from copy import deepcopy
from datetime import datetime
-from typing import Optional, Set
+from typing import Optional
from uuid import uuid4
from aiogram import Bot
@@ -57,7 +57,7 @@ def file_unique_id(media: MediaAttachment) -> str:
class MockMessageManager(MessageManagerProtocol):
def __init__(self):
- self.answered_callbacks: Set[str] = set()
+ self.answered_callbacks: set[str] = set()
self.sent_messages = []
self.last_message_id = 0
@@ -85,9 +85,9 @@ async def remove_kbd(
old_message: Optional[OldMessage],
) -> Optional[Message]:
if not old_message:
- return
+ return None
if show_mode in (ShowMode.DELETE_AND_SEND, ShowMode.NO_UPDATE):
- return
+ return None
assert isinstance(old_message, OldMessage)
message = Message(
diff --git a/src/aiogram_dialog/tools/preview.py b/src/aiogram_dialog/tools/preview.py
index a9e1c190..75d7b269 100644
--- a/src/aiogram_dialog/tools/preview.py
+++ b/src/aiogram_dialog/tools/preview.py
@@ -269,7 +269,7 @@ async def create_button(
manager.set_state(state)
try:
await dialog._callback_handler(callback_query, dialog_manager=manager)
- except Exception: # noqa: B902
+ except Exception:
logging.debug("Click %s", callback)
state = manager.current_context().state
return RenderButton(title=title, state=state.state)
@@ -297,7 +297,7 @@ async def render_input(
manager.set_state(state)
try:
await dialog._message_handler(message, dialog_manager=manager)
- except Exception: # noqa: B902
+ except Exception:
logging.debug("Input %s", content_type)
if state == manager.current_context().state:
@@ -319,22 +319,20 @@ async def render_inline_keyboard(
dialog: Dialog,
simulate_events: bool,
):
- keyboard = []
- for row in reply_markup.inline_keyboard:
- keyboard_row = []
- for button in row:
- keyboard_row.append(
- await create_button(
- title=button.text,
- callback=button.callback_data,
- manager=manager,
- dialog=dialog,
- state=state,
- simulate_events=simulate_events,
- ),
+ return [
+ [
+ await create_button(
+ title=button.text,
+ callback=button.callback_data,
+ manager=manager,
+ dialog=dialog,
+ state=state,
+ simulate_events=simulate_events,
)
- keyboard.append(keyboard_row)
- return keyboard
+ for button in row
+ ]
+ for row in reply_markup.inline_keyboard
+ ]
async def render_reply_keyboard(
diff --git a/src/aiogram_dialog/utils.py b/src/aiogram_dialog/utils.py
index de1f7768..6ddb7cde 100644
--- a/src/aiogram_dialog/utils.py
+++ b/src/aiogram_dialog/utils.py
@@ -83,7 +83,7 @@ def split_reply_callback(
def decode_reply_callback(data: str) -> str:
bytes_data = bytes(
_decode_reply_callback_byte(little, big)
- for little, big in zip(data[::2], data[1::2])
+ for little, big in zip(data[::2], data[1::2], strict=False)
)
return bytes_data.decode("utf-8")
@@ -107,13 +107,10 @@ def _transform_to_reply_button(
def transform_to_reply_keyboard(
keyboard: list[list[Union[InlineKeyboardButton, KeyboardButton]]],
) -> list[list[KeyboardButton]]:
- new_kdb = []
- for row in keyboard:
- new_row = []
- new_kdb.append(new_row)
- for button in row:
- new_row.append(_transform_to_reply_button(button))
- return new_kdb
+ return [
+ [_transform_to_reply_button(button) for button in row]
+ for row in keyboard
+ ]
def get_chat(event: ChatEvent) -> Chat:
@@ -126,6 +123,8 @@ def get_chat(event: ChatEvent) -> Chat:
if not event.message:
return Chat(id=event.from_user.id, type="")
return event.message.chat
+ else:
+ raise TypeError
def is_chat_loaded(chat: Chat) -> bool:
diff --git a/src/aiogram_dialog/widgets/common/when.py b/src/aiogram_dialog/widgets/common/when.py
index 24bf39d6..5dd9a391 100644
--- a/src/aiogram_dialog/widgets/common/when.py
+++ b/src/aiogram_dialog/widgets/common/when.py
@@ -32,7 +32,7 @@ def __call__(
def new_when_field(fieldname: str) -> Predicate:
def when_field(
- data: dict, widget: "Whenable", manager: DialogManager,
+ data: dict, widget: Whenable, manager: DialogManager,
) -> bool:
return bool(data.get(fieldname))
@@ -41,14 +41,14 @@ def when_field(
def new_when_magic(f: MagicFilter) -> Predicate:
def when_magic(
- data: dict, widget: "Whenable", manager: DialogManager,
+ data: dict, widget: Whenable, manager: DialogManager,
) -> bool:
return f.resolve(data)
return when_magic
-def true_condition(data: dict, widget: "Whenable", manager: DialogManager):
+def true_condition(data: dict, widget: Whenable, manager: DialogManager):
return True
diff --git a/src/aiogram_dialog/widgets/kbd/calendar_kbd.py b/src/aiogram_dialog/widgets/kbd/calendar_kbd.py
index 7d4aafa1..89399e01 100644
--- a/src/aiogram_dialog/widgets/kbd/calendar_kbd.py
+++ b/src/aiogram_dialog/widgets/kbd/calendar_kbd.py
@@ -254,7 +254,7 @@ async def _render_days(
end_date += timedelta(days=days_till_week_end)
# add days
today = get_today(config.timezone)
- for offset in range(0, (end_date - start_date).days, 7):
+ for offset in range(0, (end_date - start_date).days, 7): # noqa: PLR1704
row = []
for row_offset in range(7):
days_offset = timedelta(days=(offset + row_offset))
diff --git a/src/aiogram_dialog/widgets/kbd/counter.py b/src/aiogram_dialog/widgets/kbd/counter.py
index 86271f7a..abc243fd 100644
--- a/src/aiogram_dialog/widgets/kbd/counter.py
+++ b/src/aiogram_dialog/widgets/kbd/counter.py
@@ -20,7 +20,7 @@ class OnCounterEvent(Protocol):
async def __call__(
self,
event: ChatEvent,
- counter: "ManagedCounter", # noqa: F841
+ counter: "ManagedCounter", # noqa: F841, RUF100
dialog_manager: DialogManager,
):
raise NotImplementedError
diff --git a/src/aiogram_dialog/widgets/kbd/group.py b/src/aiogram_dialog/widgets/kbd/group.py
index ef526b52..a8757977 100644
--- a/src/aiogram_dialog/widgets/kbd/group.py
+++ b/src/aiogram_dialog/widgets/kbd/group.py
@@ -16,7 +16,7 @@ def __init__(
self,
*buttons: Keyboard,
id: Optional[str] = None,
- width: int = None,
+ width: Optional[int] = None,
when: WhenCondition = None,
):
super().__init__(id=id, when=when)
@@ -24,7 +24,7 @@ def __init__(
self.width = width
def find(self, widget_id):
- widget = super(Group, self).find(widget_id)
+ widget = super().find(widget_id)
if widget:
return widget
for btn in self.buttons:
diff --git a/src/aiogram_dialog/widgets/kbd/list_group.py b/src/aiogram_dialog/widgets/kbd/list_group.py
index 16454705..05087112 100644
--- a/src/aiogram_dialog/widgets/kbd/list_group.py
+++ b/src/aiogram_dialog/widgets/kbd/list_group.py
@@ -95,7 +95,7 @@ async def _process_item_callback(
widget_id=self.widget_id,
item_id=item_id,
)
- for b in self.buttons:
+ for b in self.buttons: # noqa: RET503
if await b.process_callback(callback, dialog, sub_manager):
return True
diff --git a/src/aiogram_dialog/widgets/kbd/select.py b/src/aiogram_dialog/widgets/kbd/select.py
index 2fe2c70d..f9efd8d2 100644
--- a/src/aiogram_dialog/widgets/kbd/select.py
+++ b/src/aiogram_dialog/widgets/kbd/select.py
@@ -38,7 +38,7 @@ class OnItemStateChanged(Protocol[ManagedT, T]):
async def __call__(
self,
event: ChatEvent,
- select: ManagedT, # noqa: F841
+ select: ManagedT,
dialog_manager: DialogManager,
data: T,
/,
@@ -51,7 +51,7 @@ class OnItemClick(Protocol[ManagedT, T]):
async def __call__(
self,
event: CallbackQuery,
- select: ManagedT, # noqa: F841
+ select: ManagedT,
dialog_manager: DialogManager,
data: T,
/,
@@ -143,7 +143,7 @@ def __init__(
on_state_changed: Union[
OnItemStateChanged[ManagedT, T], WidgetEventProcessor, None,
] = None,
- when: Union[str, Callable] = None,
+ when: Optional[Union[str, Callable]] = None,
):
text = Case(
{True: checked_text, False: unchecked_text},
@@ -229,7 +229,7 @@ def __init__(
OnItemStateChanged["ManagedRadio[T]", T],
WidgetEventProcessor, None,
] = None,
- when: Union[str, Callable] = None,
+ when: Optional[Union[str, Callable]] = None,
):
super().__init__(
@@ -331,7 +331,7 @@ def __init__(
OnItemStateChanged["ManagedMultiselect[T]", T],
WidgetEventProcessor, None,
] = None,
- when: Union[str, Callable] = None,
+ when: Optional[Union[str, Callable]] = None,
):
super().__init__(
checked_text=checked_text,
@@ -447,7 +447,7 @@ def __init__(
OnItemStateChanged["ManagedToggle[T]", T],
WidgetEventProcessor, None,
] = None,
- when: Union[str, Callable] = None,
+ when: Optional[Union[str, Callable]] = None,
):
super().__init__(
checked_text=text, unchecked_text=text,
diff --git a/src/aiogram_dialog/widgets/media/static.py b/src/aiogram_dialog/widgets/media/static.py
index 8053d150..239fb48e 100644
--- a/src/aiogram_dialog/widgets/media/static.py
+++ b/src/aiogram_dialog/widgets/media/static.py
@@ -19,7 +19,7 @@ def __init__(
url: Union[Text, str, None] = None,
type: ContentType = ContentType.PHOTO,
use_pipe: bool = False,
- media_params: dict = None,
+ media_params: Optional[dict] = None,
when: WhenCondition = None,
):
super().__init__(when=when)
diff --git a/src/aiogram_dialog/window.py b/src/aiogram_dialog/window.py
index 618a23eb..832f30fc 100644
--- a/src/aiogram_dialog/window.py
+++ b/src/aiogram_dialog/window.py
@@ -77,6 +77,7 @@ async def render_media(
) -> Optional[MediaAttachment]:
if self.media:
return await self.media.render_media(data, manager)
+ return None
async def render_kbd(
self, data: dict, manager: DialogManager,
@@ -128,7 +129,7 @@ async def render(
chat = manager.middleware_data["event_chat"]
try:
current_data = await self.load_data(dialog, manager)
- except Exception: # noqa: B902
+ except Exception:
logger.error("Cannot get window data for state %s", self.state)
raise
try:
@@ -145,7 +146,7 @@ async def render(
disable_web_page_preview=self.disable_web_page_preview,
media=await self.render_media(current_data, manager),
)
- except Exception: # noqa: B902
+ except Exception:
logger.error("Cannot render window for state %s", self.state)
raise
diff --git a/tests/test_click.py b/tests/test_click.py
index 0ec5d22f..54ab6f29 100644
--- a/tests/test_click.py
+++ b/tests/test_click.py
@@ -8,7 +8,11 @@
from aiogram.types import Message
from aiogram_dialog import (
- Dialog, DialogManager, setup_dialogs, StartMode, Window,
+ Dialog,
+ DialogManager,
+ StartMode,
+ Window,
+ setup_dialogs,
)
from aiogram_dialog.test_tools import BotClient, MockMessageManager
from aiogram_dialog.test_tools.keyboard import InlineButtonTextLocator
diff --git a/tests/test_create.py b/tests/test_create.py
index 7d6764f9..5a69a4e1 100644
--- a/tests/test_create.py
+++ b/tests/test_create.py
@@ -1,7 +1,7 @@
from aiogram import Dispatcher
from aiogram.fsm.state import State, StatesGroup
-from aiogram_dialog import Dialog, setup_dialogs, Window
+from aiogram_dialog import Dialog, Window, setup_dialogs
from aiogram_dialog.widgets.text import Format
diff --git a/tests/test_events.py b/tests/test_events.py
index 9a9c5017..aa29ec50 100644
--- a/tests/test_events.py
+++ b/tests/test_events.py
@@ -7,7 +7,11 @@
from aiogram.types import ChatMemberMember, ChatMemberOwner
from aiogram_dialog import (
- Dialog, DialogManager, setup_dialogs, StartMode, Window,
+ Dialog,
+ DialogManager,
+ StartMode,
+ Window,
+ setup_dialogs,
)
from aiogram_dialog.test_tools import BotClient, MockMessageManager
from aiogram_dialog.test_tools.memory_storage import JsonMemoryStorage
diff --git a/tests/test_group.py b/tests/test_group.py
index daba4b59..89166fa9 100644
--- a/tests/test_group.py
+++ b/tests/test_group.py
@@ -7,9 +7,13 @@
from aiogram.fsm.state import State, StatesGroup
from aiogram_dialog import (
- Dialog, DialogManager, setup_dialogs, StartMode, Window,
+ Dialog,
+ DialogManager,
+ StartMode,
+ Window,
+ setup_dialogs,
)
-from aiogram_dialog.api.entities import AccessSettings, GROUP_STACK_ID
+from aiogram_dialog.api.entities import GROUP_STACK_ID, AccessSettings
from aiogram_dialog.test_tools import BotClient, MockMessageManager
from aiogram_dialog.test_tools.keyboard import InlineButtonTextLocator
from aiogram_dialog.test_tools.memory_storage import JsonMemoryStorage
@@ -159,7 +163,8 @@ async def test_same_user(dp, client, message_manager):
async def test_shared_stack(dp, client, second_client, message_manager):
dp.message.register(start_shared, CommandStart())
await client.send("/start")
- await asyncio.sleep(0.01) # synchronization workaround, fixme
+ await asyncio.sleep(0.02) # synchronization workaround, fixme
+
first_message = message_manager.one_message()
assert first_message.text == "stub"
message_manager.reset_history()
diff --git a/tests/test_nested_transitions.py b/tests/test_nested_transitions.py
index 53c77c22..82678663 100644
--- a/tests/test_nested_transitions.py
+++ b/tests/test_nested_transitions.py
@@ -5,7 +5,11 @@
from aiogram.types import Message
from aiogram_dialog import (
- Dialog, DialogManager, setup_dialogs, StartMode, Window,
+ Dialog,
+ DialogManager,
+ StartMode,
+ Window,
+ setup_dialogs,
)
from aiogram_dialog.test_tools import BotClient, MockMessageManager
from aiogram_dialog.test_tools.keyboard import InlineButtonTextLocator
diff --git a/tests/test_transitions.py b/tests/test_transitions.py
index 64ef53bc..bc844bd9 100644
--- a/tests/test_transitions.py
+++ b/tests/test_transitions.py
@@ -5,7 +5,11 @@
from aiogram.types import Message
from aiogram_dialog import (
- Dialog, DialogManager, setup_dialogs, StartMode, Window,
+ Dialog,
+ DialogManager,
+ StartMode,
+ Window,
+ setup_dialogs,
)
from aiogram_dialog.test_tools import BotClient, MockMessageManager
from aiogram_dialog.test_tools.keyboard import InlineButtonTextLocator
diff --git a/tests/widgets/kbd/test_group.py b/tests/widgets/kbd/test_group.py
index 7d7b7c60..5dd094bf 100644
--- a/tests/widgets/kbd/test_group.py
+++ b/tests/widgets/kbd/test_group.py
@@ -7,7 +7,11 @@
from aiogram.types import Message
from aiogram_dialog import (
- Dialog, DialogManager, setup_dialogs, StartMode, Window,
+ Dialog,
+ DialogManager,
+ StartMode,
+ Window,
+ setup_dialogs,
)
from aiogram_dialog.test_tools import BotClient, MockMessageManager
from aiogram_dialog.test_tools.keyboard import InlineButtonTextLocator
diff --git a/tests/widgets/media/test_media_message.py b/tests/widgets/media/test_media_message.py
index 6d9087be..174ade26 100644
--- a/tests/widgets/media/test_media_message.py
+++ b/tests/widgets/media/test_media_message.py
@@ -8,9 +8,9 @@
from aiogram_dialog import (
Dialog,
DialogManager,
- setup_dialogs,
StartMode,
Window,
+ setup_dialogs,
)
from aiogram_dialog.test_tools import BotClient, MockMessageManager
from aiogram_dialog.widgets.media.static import StaticMedia
From 8f0070d111b74f43cb733b79e52b4646480c7586 Mon Sep 17 00:00:00 2001
From: chiri <2alivemafia@gmail.com>
Date: Wed, 6 Nov 2024 11:11:31 +0300
Subject: [PATCH 12/29] fix workflow
---
.github/workflows/setup.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/setup.yml b/.github/workflows/setup.yml
index 41847be8..f2fd1847 100644
--- a/.github/workflows/setup.yml
+++ b/.github/workflows/setup.yml
@@ -38,8 +38,8 @@ jobs:
- name: Install dependencies
run: |
- uv pip install . -r requirements_dev.txt
- uv pip install diagrams
+ uv pip install . -r requirements_dev.txt --system
+ uv pip install diagrams --system
- name: Run Ruff
run: ruff check src/aiogram_dialog tests example
From 06c911c68850be59f841fc95b61fb3743b996917 Mon Sep 17 00:00:00 2001
From: chiri <2alivemafia@gmail.com>
Date: Wed, 6 Nov 2024 11:17:40 +0300
Subject: [PATCH 13/29] fix code for python 3.9
---
src/aiogram_dialog/dialog.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/aiogram_dialog/dialog.py b/src/aiogram_dialog/dialog.py
index 6b2ea5dc..a40891c9 100644
--- a/src/aiogram_dialog/dialog.py
+++ b/src/aiogram_dialog/dialog.py
@@ -61,7 +61,7 @@ def __init__(
raise ValueError(f"Multiple windows with state {state}")
self._states.append(state)
self.windows: dict[State, WindowProtocol] = dict(
- zip(self._states, windows, strict=False),
+ zip(self._states, windows),
)
self.on_start = on_start
self.on_close = on_close
From 9c2a5936b4ebe6ca00af849ec40a38a54ee47aac Mon Sep 17 00:00:00 2001
From: chiri <2alivemafia@gmail.com>
Date: Wed, 6 Nov 2024 11:25:20 +0300
Subject: [PATCH 14/29] fix tests for python 3.9
---
src/aiogram_dialog/utils.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/aiogram_dialog/utils.py b/src/aiogram_dialog/utils.py
index 6ddb7cde..57a9831a 100644
--- a/src/aiogram_dialog/utils.py
+++ b/src/aiogram_dialog/utils.py
@@ -83,7 +83,7 @@ def split_reply_callback(
def decode_reply_callback(data: str) -> str:
bytes_data = bytes(
_decode_reply_callback_byte(little, big)
- for little, big in zip(data[::2], data[1::2], strict=False)
+ for little, big in zip(data[::2], data[1::2])
)
return bytes_data.decode("utf-8")
From 6897cc64917ab1946ee15be55cebfc5d3b1779fa Mon Sep 17 00:00:00 2001
From: chiri <2alivemafia@gmail.com>
Date: Wed, 6 Nov 2024 17:06:42 +0300
Subject: [PATCH 15/29] fix: improve code readability
---
src/aiogram_dialog/widgets/kbd/select.py | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/aiogram_dialog/widgets/kbd/select.py b/src/aiogram_dialog/widgets/kbd/select.py
index f9efd8d2..5d4571d9 100644
--- a/src/aiogram_dialog/widgets/kbd/select.py
+++ b/src/aiogram_dialog/widgets/kbd/select.py
@@ -352,7 +352,7 @@ def _is_text_checked(
if manager.is_preview():
return (
# just stupid way to make it differ in preview
- ord(item_id[-1]) % 2 == 1
+ ord(item_id[-1]) % 2 == 1
)
return self.is_checked(item_id, manager)
@@ -387,9 +387,11 @@ async def set_checked(
if not checked and len(data) > self.min_selected:
data.remove(item_id_str)
changed = True
- elif checked and self.max_selected == 0 or self.max_selected > len(data): # noqa: E501
- data.append(item_id_str)
- changed = True
+ else: # noqa: PLR5501
+ if checked: # noqa: SIM102
+ if self.max_selected == 0 or self.max_selected > len(data):
+ data.append(item_id_str)
+ changed = True
if changed:
self.set_widget_data(manager, data)
await self._process_on_state_changed(event, item_id_str, manager)
From c8cfd0aeabd258671909913405649eb8c1616518 Mon Sep 17 00:00:00 2001
From: chiri <2alivemafia@gmail.com>
Date: Wed, 6 Nov 2024 17:21:15 +0300
Subject: [PATCH 16/29] fix: enable ignored ruff rules: PT001, PT023, PLW2901,
B904, RUF012, N804, B008, RUF009 and sort rules by name
---
.ruff.toml | 48 ++++++++++++---------------
src/aiogram_dialog/context/storage.py | 2 +-
tests/test_events.py | 6 ++--
tests/test_group.py | 8 ++---
tests/test_nested_transitions.py | 6 ++--
tests/test_transitions.py | 6 ++--
tests/widgets/conftest.py | 2 +-
tests/widgets/text/test_jinja.py | 2 +-
8 files changed, 37 insertions(+), 43 deletions(-)
diff --git a/.ruff.toml b/.ruff.toml
index 6d1b7998..dfb7e3d4 100644
--- a/.ruff.toml
+++ b/.ruff.toml
@@ -7,48 +7,42 @@ exclude = ["docs"]
lint.select = ["ALL"]
lint.ignore = [
- "ARG",
"ANN",
+ "ARG",
"D",
"DTZ",
"TD",
+ "A002",
+ "ASYNC230",
+ "BLE001",
"EM101",
"EM102",
- "PT001",
- "PT023",
- "SIM108",
- "SIM114",
- "TRY003",
- "TCH003",
- "PLW2901",
- "RET505",
- "PLR0913",
- "UP038",
- "TCH001",
- "SIM103",
- "ISC003",
- "A002",
"FA100",
- "TRY400",
"FBT001",
"FBT002",
- "S311",
- "N818",
- "B904",
"FIX002",
- "RUF012",
+ "ISC002",
+ "ISC003",
+ "N818",
+ "PLR0913",
+ "PLW2901",
+ "PYI034",
+ "RET505",
+ "S311",
+ "SIM103",
+ "SIM108",
+ "SIM114",
+ "TCH001",
"TCH002",
+ "TCH003",
+ "TRY003",
"TRY201",
- "ISC002",
- "ASYNC230",
+ "TRY400",
"UP007",
- "N804",
- "B008",
- "BLE001",
- "RUF009",
- "PYI034",
+ "UP038",
]
+
[lint.per-file-ignores]
"src/aiogram_dialog/tools/**" = [
"S101",
diff --git a/src/aiogram_dialog/context/storage.py b/src/aiogram_dialog/context/storage.py
index e1c22fd6..f7766161 100644
--- a/src/aiogram_dialog/context/storage.py
+++ b/src/aiogram_dialog/context/storage.py
@@ -167,7 +167,7 @@ def _state(self, state: str) -> State:
if real_state.state == state:
return real_state
except KeyError:
- raise UnknownState(f"Unknown state group {group}")
+ raise UnknownState(f"Unknown state group {group}") from None
raise UnknownState(f"Unknown state {state}")
def _parse_access_settings(
diff --git a/tests/test_events.py b/tests/test_events.py
index aa29ec50..b2d17b25 100644
--- a/tests/test_events.py
+++ b/tests/test_events.py
@@ -32,12 +32,12 @@ async def start(event: Any, dialog_manager: DialogManager):
await dialog_manager.start(MainSG.start, mode=StartMode.RESET_STACK)
-@pytest.fixture()
+@pytest.fixture
def message_manager():
return MockMessageManager()
-@pytest.fixture()
+@pytest.fixture
def dp(message_manager):
dp = Dispatcher(storage=JsonMemoryStorage())
dp.include_router(Dialog(window))
@@ -45,7 +45,7 @@ def dp(message_manager):
return dp
-@pytest.fixture()
+@pytest.fixture
def client(dp):
return BotClient(dp)
diff --git a/tests/test_group.py b/tests/test_group.py
index 89166fa9..5c8d0651 100644
--- a/tests/test_group.py
+++ b/tests/test_group.py
@@ -47,12 +47,12 @@ async def add_shared(event: Any, dialog_manager: DialogManager):
))
-@pytest.fixture()
+@pytest.fixture
def message_manager():
return MockMessageManager()
-@pytest.fixture()
+@pytest.fixture
def dp(message_manager):
dp = Dispatcher(storage=JsonMemoryStorage())
dp.include_router(Dialog(window))
@@ -60,12 +60,12 @@ def dp(message_manager):
return dp
-@pytest.fixture()
+@pytest.fixture
def client(dp):
return BotClient(dp, chat_id=-1, user_id=1, chat_type="group")
-@pytest.fixture()
+@pytest.fixture
def second_client(dp):
return BotClient(dp, chat_id=-1, user_id=2, chat_type="group")
diff --git a/tests/test_nested_transitions.py b/tests/test_nested_transitions.py
index 82678663..e8d96180 100644
--- a/tests/test_nested_transitions.py
+++ b/tests/test_nested_transitions.py
@@ -46,17 +46,17 @@ async def on_process_result_sub(_, __, dialog_manager: DialogManager):
await dialog_manager.done()
-@pytest.fixture()
+@pytest.fixture
def message_manager() -> MockMessageManager:
return MockMessageManager()
-@pytest.fixture()
+@pytest.fixture
def client(dp) -> BotClient:
return BotClient(dp)
-@pytest.fixture()
+@pytest.fixture
def dp(message_manager: MockMessageManager):
dp = Dispatcher(storage=JsonMemoryStorage())
dp.message.register(start, CommandStart())
diff --git a/tests/test_transitions.py b/tests/test_transitions.py
index bc844bd9..9334dedd 100644
--- a/tests/test_transitions.py
+++ b/tests/test_transitions.py
@@ -31,17 +31,17 @@ async def start(message: Message, dialog_manager: DialogManager):
await dialog_manager.start(MainSG.start, mode=StartMode.RESET_STACK)
-@pytest.fixture()
+@pytest.fixture
def message_manager() -> MockMessageManager:
return MockMessageManager()
-@pytest.fixture()
+@pytest.fixture
def client(dp) -> BotClient:
return BotClient(dp)
-@pytest.fixture()
+@pytest.fixture
def dp(message_manager: MockMessageManager):
dp = Dispatcher(storage=JsonMemoryStorage())
dp.message.register(start, CommandStart())
diff --git a/tests/widgets/conftest.py b/tests/widgets/conftest.py
index 70b5cc02..16f2912f 100644
--- a/tests/widgets/conftest.py
+++ b/tests/widgets/conftest.py
@@ -7,7 +7,7 @@
from aiogram_dialog.api.entities import Context
-@pytest.fixture()
+@pytest.fixture
def mock_manager() -> DialogManager:
manager = MagicMock()
context = Context(
diff --git a/tests/widgets/text/test_jinja.py b/tests/widgets/text/test_jinja.py
index 5a94f200..47c1cb7e 100644
--- a/tests/widgets/text/test_jinja.py
+++ b/tests/widgets/text/test_jinja.py
@@ -4,7 +4,7 @@
from aiogram_dialog.widgets.text import Jinja
-@pytest.fixture()
+@pytest.fixture
def mock_manager(mock_manager) -> DialogManager:
mock_manager.middleware_data = {}
return mock_manager
From 90475d9b305c3d15089ba35eb8a6ff29fa4a86dd Mon Sep 17 00:00:00 2001
From: Andrey Tikhonov <17@itishka.org>
Date: Wed, 6 Nov 2024 15:27:41 +0100
Subject: [PATCH 17/29] Update to restart pipeline
---
src/aiogram_dialog/widgets/kbd/copy.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/aiogram_dialog/widgets/kbd/copy.py b/src/aiogram_dialog/widgets/kbd/copy.py
index 10befb2f..c755180f 100644
--- a/src/aiogram_dialog/widgets/kbd/copy.py
+++ b/src/aiogram_dialog/widgets/kbd/copy.py
@@ -16,9 +16,9 @@ def __init__(
copy_text: Text,
when: WhenCondition = None,
) -> None:
+ super().__init__(when=when)
self._text = text
self._copy_text = copy_text
- super().__init__(when=when)
async def _render_keyboard(
self,
From 2ed7d6b5962dc4207fcbb7109555e5427a83da69 Mon Sep 17 00:00:00 2001
From: Andrey Tikhonov <17@itishka.org>
Date: Wed, 6 Nov 2024 15:34:18 +0100
Subject: [PATCH 18/29] fix trailing comma
---
src/aiogram_dialog/widgets/kbd/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/aiogram_dialog/widgets/kbd/__init__.py b/src/aiogram_dialog/widgets/kbd/__init__.py
index ba4382e9..c955d3b5 100644
--- a/src/aiogram_dialog/widgets/kbd/__init__.py
+++ b/src/aiogram_dialog/widgets/kbd/__init__.py
@@ -41,7 +41,7 @@
"ListGroup",
"ManagedListGroup",
"StubScroll",
- "CopyText"
+ "CopyText",
]
from .base import Keyboard
From fc7e852a3e0112a5b838f37bc8f5e5bafdc4b01a Mon Sep 17 00:00:00 2001
From: chiri <2alivemafia@gmail.com>
Date: Wed, 6 Nov 2024 17:39:41 +0300
Subject: [PATCH 19/29] drop python 3.8 from docs examples
---
.../example.py | 18 ++++++++---------
docs/widgets/hiding/example.py | 12 +++++------
docs/widgets/keyboard/calendar/custom.py | 15 ++++++++------
docs/widgets/text/case/example.py | 20 +++++++++----------
4 files changed, 32 insertions(+), 33 deletions(-)
diff --git a/docs/widgets/custom_widgets/switch_inline_query_current_chat/example.py b/docs/widgets/custom_widgets/switch_inline_query_current_chat/example.py
index d62182d4..ddd57de0 100644
--- a/docs/widgets/custom_widgets/switch_inline_query_current_chat/example.py
+++ b/docs/widgets/custom_widgets/switch_inline_query_current_chat/example.py
@@ -1,9 +1,7 @@
-from typing import Dict, List
-
-from aiogram.filters.state import StatesGroup, State
+from aiogram.filters.state import State, StatesGroup
from aiogram.types import InlineKeyboardButton
-from aiogram_dialog import Dialog, Window
-from aiogram_dialog import DialogManager
+
+from aiogram_dialog import Dialog, DialogManager, Window
from aiogram_dialog.widgets.kbd import SwitchInlineQuery
from aiogram_dialog.widgets.text import Const
@@ -11,9 +9,9 @@
class SwitchInlineQueryCurrentChat(SwitchInlineQuery):
async def _render_keyboard(
self,
- data: Dict,
+ data: dict,
manager: DialogManager,
- ) -> List[List[InlineKeyboardButton]]:
+ ) -> list[list[InlineKeyboardButton]]:
return [
[
InlineKeyboardButton(
@@ -34,8 +32,8 @@ class MySG(StatesGroup):
Window(
SwitchInlineQueryCurrentChat(
Const("Some search"), # Button text
- Const("query") # additional query. Optional
+ Const("query"), # additional query. Optional
),
- state=MySG.main
- )
+ state=MySG.main,
+ ),
)
diff --git a/docs/widgets/hiding/example.py b/docs/widgets/hiding/example.py
index de3cd53a..5b1c777a 100644
--- a/docs/widgets/hiding/example.py
+++ b/docs/widgets/hiding/example.py
@@ -1,11 +1,9 @@
-from typing import Dict
-
-from aiogram.filters.state import StatesGroup, State
+from aiogram.filters.state import State, StatesGroup
from magic_filter import F
-from aiogram_dialog import Window, DialogManager
+from aiogram_dialog import DialogManager, Window
from aiogram_dialog.widgets.common import Whenable
-from aiogram_dialog.widgets.kbd import Button, Row, Group
+from aiogram_dialog.widgets.kbd import Button, Group, Row
from aiogram_dialog.widgets.text import Const, Format, Multi
@@ -20,7 +18,7 @@ async def get_data(**kwargs):
}
-def is_tishka17(data: Dict, widget: Whenable, manager: DialogManager):
+def is_tishka17(data: dict, widget: Whenable, manager: DialogManager):
return data.get("name") == "Tishka17"
@@ -28,7 +26,7 @@ def is_tishka17(data: Dict, widget: Whenable, manager: DialogManager):
Multi(
Const("Hello"),
Format("{name}", when="extended"),
- sep=" "
+ sep=" ",
),
Group(
Row(
diff --git a/docs/widgets/keyboard/calendar/custom.py b/docs/widgets/keyboard/calendar/custom.py
index d3eb30aa..efb8a1b0 100644
--- a/docs/widgets/keyboard/calendar/custom.py
+++ b/docs/widgets/keyboard/calendar/custom.py
@@ -1,17 +1,20 @@
-from typing import Dict
-
from aiogram_dialog import DialogManager
from aiogram_dialog.widgets.kbd import (
- Calendar, CalendarScope, CalendarUserConfig,
+ Calendar,
+ CalendarScope,
+ CalendarUserConfig,
)
from aiogram_dialog.widgets.kbd.calendar_kbd import (
- CalendarDaysView, CalendarMonthView, CalendarScopeView, CalendarYearsView,
+ CalendarDaysView,
+ CalendarMonthView,
+ CalendarScopeView,
+ CalendarYearsView,
)
from aiogram_dialog.widgets.text import Const, Format
class CustomCalendar(Calendar):
- def _init_views(self) -> Dict[CalendarScope, CalendarScopeView]:
+ def _init_views(self) -> dict[CalendarScope, CalendarScopeView]:
return {
CalendarScope.DAYS: CalendarDaysView(
self._item_callback_data, self.config,
@@ -28,7 +31,7 @@ def _init_views(self) -> Dict[CalendarScope, CalendarScopeView]:
async def _get_user_config(
self,
- data: Dict,
+ data: dict,
manager: DialogManager,
) -> CalendarUserConfig:
return CalendarUserConfig(
diff --git a/docs/widgets/text/case/example.py b/docs/widgets/text/case/example.py
index 0181477a..cbe72d5e 100644
--- a/docs/widgets/text/case/example.py
+++ b/docs/widgets/text/case/example.py
@@ -1,11 +1,11 @@
-from typing import Any, Dict
+from typing import Any
+from aiogram.filters.state import State, StatesGroup
from magic_filter import F
-from aiogram.filters.state import StatesGroup, State
+from aiogram_dialog import Dialog, DialogManager, Window
+from aiogram_dialog.widgets.text import Case, Const, Format
-from aiogram_dialog import Window, DialogManager, Dialog
-from aiogram_dialog.widgets.text import Const, Format, Case
class MySG(StatesGroup):
window1 = State()
@@ -35,7 +35,7 @@ async def get_data(**kwargs):
# The result of this function will be used to select wich option of ``Case`` widget to show.
#
# `text2` will produce text `42 is even!`
-def parity_selector(data: Dict, case: Case, manager: DialogManager):
+def parity_selector(data: dict, case: Case, manager: DialogManager):
return data["number"] % 2
@@ -63,8 +63,8 @@ def parity_selector(data: Dict, case: Case, manager: DialogManager):
async def on_dialog_start(start_data: Any, manager: DialogManager):
- manager.dialog_data['user'] = {
- 'test_result': True,
+ manager.dialog_data["user"] = {
+ "test_result": True,
}
@@ -74,7 +74,7 @@ async def on_dialog_start(start_data: Any, manager: DialogManager):
text2,
text3,
state=MySG.window1,
- getter=get_data
+ getter=get_data,
),
- on_start=on_dialog_start
-)
\ No newline at end of file
+ on_start=on_dialog_start,
+)
From a60844d67a5c4524f9946d7681f676e5f9e083b4 Mon Sep 17 00:00:00 2001
From: Kostiantyn Kriuchkov <36363097+Latand@users.noreply.github.com>
Date: Thu, 7 Nov 2024 15:09:16 +0200
Subject: [PATCH 20/29] Update message_manager.py
---
src/aiogram_dialog/manager/message_manager.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/aiogram_dialog/manager/message_manager.py b/src/aiogram_dialog/manager/message_manager.py
index 386d9b37..7f740a8b 100644
--- a/src/aiogram_dialog/manager/message_manager.py
+++ b/src/aiogram_dialog/manager/message_manager.py
@@ -238,6 +238,8 @@ async def remove_inline_kbd(
pass
elif "message to edit not found" in err.message:
pass
+ elif "MESSAGE_ID_INVALID" in err.message:
+ pass
else:
raise err
From f72f37959542eb6fc94ae6739e3ca9f9de4d96b6 Mon Sep 17 00:00:00 2001
From: Kurosawa <145038102+KurosawaAngel@users.noreply.github.com>
Date: Thu, 7 Nov 2024 22:57:47 +0500
Subject: [PATCH 21/29] fix edit voice
---
src/aiogram_dialog/api/entities/new_message.py | 2 ++
src/aiogram_dialog/api/entities/stack.py | 2 ++
src/aiogram_dialog/manager/manager.py | 6 +++++-
src/aiogram_dialog/manager/message_manager.py | 11 +++++++++--
4 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/src/aiogram_dialog/api/entities/new_message.py b/src/aiogram_dialog/api/entities/new_message.py
index 062f794f..4ac6883a 100644
--- a/src/aiogram_dialog/api/entities/new_message.py
+++ b/src/aiogram_dialog/api/entities/new_message.py
@@ -2,6 +2,7 @@
from enum import Enum
from typing import Optional, Union
+from aiogram.enums import ContentType
from aiogram.types import (
Chat,
ForceReply,
@@ -30,6 +31,7 @@ class OldMessage:
text: Union[str, None, UnknownText] = None
has_reply_keyboard: bool = False
business_connection_id: Optional[str] = None
+ content_type: Optional[ContentType] = None
@dataclass
diff --git a/src/aiogram_dialog/api/entities/stack.py b/src/aiogram_dialog/api/entities/stack.py
index 3256d018..27b3f01f 100644
--- a/src/aiogram_dialog/api/entities/stack.py
+++ b/src/aiogram_dialog/api/entities/stack.py
@@ -4,6 +4,7 @@
from dataclasses import dataclass, field
from typing import Optional
+from aiogram.enums import ContentType
from aiogram.fsm.state import State
from aiogram_dialog.api.exceptions import DialogStackOverflow
@@ -47,6 +48,7 @@ class Stack:
last_income_media_group_id: Optional[str] = field(
compare=False, default=None,
)
+ content_type: Optional[ContentType] = field(compare=False, default=None)
access_settings: Optional[AccessSettings] = None
@property
diff --git a/src/aiogram_dialog/manager/manager.py b/src/aiogram_dialog/manager/manager.py
index 680ef54e..79cef84b 100644
--- a/src/aiogram_dialog/manager/manager.py
+++ b/src/aiogram_dialog/manager/manager.py
@@ -421,6 +421,7 @@ def _get_message_from_callback(
chat=event_context.chat,
message_id=current_message.message_id,
business_connection_id=event_context.business_connection_id,
+ content_type=current_message.content_type,
)
elif not stack or not stack.last_message_id:
return None
@@ -433,6 +434,7 @@ def _get_message_from_callback(
chat=event_context.chat,
message_id=stack.last_message_id,
business_connection_id=event_context.business_connection_id,
+ content_type=stack.content_type,
)
def _get_last_message(self) -> Optional[OldMessage]:
@@ -457,14 +459,16 @@ def _get_last_message(self) -> Optional[OldMessage]:
chat=event_context.chat,
message_id=stack.last_message_id,
business_connection_id=event_context.business_connection_id,
+ content_type=stack.content_type,
)
- def _save_last_message(self, message: OldMessage):
+ def _save_last_message(self, message: OldMessage) -> None:
stack = self.current_stack()
stack.last_message_id = message.message_id
stack.last_media_id = message.media_id
stack.last_media_unique_id = message.media_uniq_id
stack.last_reply_keyboard = message.has_reply_keyboard
+ stack.content_type = message.content_type
def _calc_show_mode(self) -> ShowMode: # noqa: PLR0911
if self.show_mode is not ShowMode.AUTO:
diff --git a/src/aiogram_dialog/manager/message_manager.py b/src/aiogram_dialog/manager/message_manager.py
index 7f740a8b..128f730d 100644
--- a/src/aiogram_dialog/manager/message_manager.py
+++ b/src/aiogram_dialog/manager/message_manager.py
@@ -71,6 +71,7 @@ def _combine(sent_message: NewMessage, message_result: Message) -> OldMessage:
media_uniq_id=(media_id.file_unique_id if media_id else None),
media_id=(media_id.file_id if media_id else None),
business_connection_id=message_result.business_connection_id,
+ content_type=message_result.content_type,
)
@@ -116,6 +117,9 @@ def need_reply_keyboard(self, new_message: Optional[NewMessage]) -> bool:
return False
return isinstance(new_message.reply_markup, ReplyKeyboardMarkup)
+ def had_voice(self, old_message: OldMessage) -> bool:
+ return old_message.content_type == ContentType.VOICE
+
def _message_changed(
self, new_message: NewMessage, old_message: OldMessage,
) -> bool:
@@ -140,9 +144,12 @@ def _can_edit(self, new_message: NewMessage,
# we cannot edit message if media removed
if self.had_media(old_message) and not self.need_media(new_message):
return False
+ # we cannot edit a message if there was voice
+ if self.had_voice(old_message):
+ return False
return not (
- self.had_reply_keyboard(old_message) or
- self.need_reply_keyboard(new_message)
+ self.had_reply_keyboard(old_message)
+ or self.need_reply_keyboard(new_message)
)
async def show_message(
From 5552ee2acf958df25b7e32f92f1ea177a40b2310 Mon Sep 17 00:00:00 2001
From: Kurosawa <145038102+KurosawaAngel@users.noreply.github.com>
Date: Thu, 7 Nov 2024 23:42:53 +0500
Subject: [PATCH 22/29] add voice added check
---
src/aiogram_dialog/manager/message_manager.py | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/aiogram_dialog/manager/message_manager.py b/src/aiogram_dialog/manager/message_manager.py
index 128f730d..f5836157 100644
--- a/src/aiogram_dialog/manager/message_manager.py
+++ b/src/aiogram_dialog/manager/message_manager.py
@@ -120,6 +120,12 @@ def need_reply_keyboard(self, new_message: Optional[NewMessage]) -> bool:
def had_voice(self, old_message: OldMessage) -> bool:
return old_message.content_type == ContentType.VOICE
+ def need_voice(self, new_message: NewMessage) -> bool:
+ return (
+ new_message.media is not None
+ and new_message.media.type == ContentType.VOICE
+ )
+
def _message_changed(
self, new_message: NewMessage, old_message: OldMessage,
) -> bool:
@@ -145,7 +151,7 @@ def _can_edit(self, new_message: NewMessage,
if self.had_media(old_message) and not self.need_media(new_message):
return False
# we cannot edit a message if there was voice
- if self.had_voice(old_message):
+ if self.had_voice(old_message) or self.need_voice(new_message):
return False
return not (
self.had_reply_keyboard(old_message)
From 460a04f0522d01f0d7c1fd4ca3a4d003ddc5f43c Mon Sep 17 00:00:00 2001
From: chiri <2alivemafia@gmail.com>
Date: Mon, 11 Nov 2024 17:32:06 +0300
Subject: [PATCH 23/29] add tests for python 3.13
---
.github/workflows/setup.yml | 1 +
pyproject.toml | 2 ++
2 files changed, 3 insertions(+)
diff --git a/.github/workflows/setup.yml b/.github/workflows/setup.yml
index f2fd1847..993e3cf7 100644
--- a/.github/workflows/setup.yml
+++ b/.github/workflows/setup.yml
@@ -25,6 +25,7 @@ jobs:
- "3.10"
- "3.11"
- "3.12"
+ - "3.13"
steps:
- uses: actions/checkout@v2
diff --git a/pyproject.toml b/pyproject.toml
index 84c18f36..d45f2889 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -24,6 +24,7 @@ classifiers = [
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
+ "Programming Language :: Python :: 3.13",
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent",
@@ -32,6 +33,7 @@ dependencies = [
"aiogram>=3.14.0",
"jinja2",
"cachetools>=4.0.0,<6.0.0",
+ "diagrams>=0.24.1",
]
[project.optional-dependencies]
tools = [
From b7856331ed998a4a09f1f0405aaf35b4a3714a74 Mon Sep 17 00:00:00 2001
From: chiri <2alivemafia@gmail.com>
Date: Mon, 11 Nov 2024 17:39:30 +0300
Subject: [PATCH 24/29] fix pyproject
---
pyproject.toml | 1 -
1 file changed, 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index d45f2889..14b83f88 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -33,7 +33,6 @@ dependencies = [
"aiogram>=3.14.0",
"jinja2",
"cachetools>=4.0.0,<6.0.0",
- "diagrams>=0.24.1",
]
[project.optional-dependencies]
tools = [
From d1b2e5ca4009dafed872bdc06295a988b6c73371 Mon Sep 17 00:00:00 2001
From: Andrey Tikhonov <17@itishka.org>
Date: Wed, 11 Dec 2024 23:41:52 +0100
Subject: [PATCH 25/29] link preview prototype
---
.../api/entities/new_message.py | 2 +
src/aiogram_dialog/api/internal/__init__.py | 3 +-
src/aiogram_dialog/api/internal/widgets.py | 11 ++++
src/aiogram_dialog/manager/message_manager.py | 13 ++--
.../widgets/link_preview/__init__.py | 3 +
.../widgets/link_preview/base.py | 61 +++++++++++++++++++
src/aiogram_dialog/widgets/utils.py | 25 +++++++-
src/aiogram_dialog/window.py | 12 ++++
8 files changed, 122 insertions(+), 8 deletions(-)
create mode 100644 src/aiogram_dialog/widgets/link_preview/__init__.py
create mode 100644 src/aiogram_dialog/widgets/link_preview/base.py
diff --git a/src/aiogram_dialog/api/entities/new_message.py b/src/aiogram_dialog/api/entities/new_message.py
index 4ac6883a..e360563a 100644
--- a/src/aiogram_dialog/api/entities/new_message.py
+++ b/src/aiogram_dialog/api/entities/new_message.py
@@ -7,6 +7,7 @@
Chat,
ForceReply,
InlineKeyboardMarkup,
+ LinkPreviewOptions,
ReplyKeyboardMarkup,
ReplyKeyboardRemove,
)
@@ -45,3 +46,4 @@ class NewMessage:
show_mode: ShowMode = ShowMode.AUTO
disable_web_page_preview: Optional[bool] = None
media: Optional[MediaAttachment] = None
+ link_preview_options: Optional[LinkPreviewOptions] = None
diff --git a/src/aiogram_dialog/api/internal/__init__.py b/src/aiogram_dialog/api/internal/__init__.py
index 62dcf102..2dc28901 100644
--- a/src/aiogram_dialog/api/internal/__init__.py
+++ b/src/aiogram_dialog/api/internal/__init__.py
@@ -4,7 +4,7 @@
"CALLBACK_DATA_KEY", "CONTEXT_KEY", "EVENT_SIMULATED",
"STACK_KEY", "STORAGE_KEY",
"ButtonVariant", "DataGetter", "InputWidget", "KeyboardWidget",
- "MediaWidget", "RawKeyboard", "TextWidget", "Widget",
+ "LinkPreviewWidget", "MediaWidget", "RawKeyboard", "TextWidget", "Widget",
"WindowProtocol",
]
@@ -24,6 +24,7 @@
DataGetter,
InputWidget,
KeyboardWidget,
+ LinkPreviewWidget,
MediaWidget,
RawKeyboard,
TextWidget,
diff --git a/src/aiogram_dialog/api/internal/widgets.py b/src/aiogram_dialog/api/internal/widgets.py
index c3976817..8472b216 100644
--- a/src/aiogram_dialog/api/internal/widgets.py
+++ b/src/aiogram_dialog/api/internal/widgets.py
@@ -12,6 +12,7 @@
CallbackQuery,
InlineKeyboardButton,
KeyboardButton,
+ LinkPreviewOptions,
Message,
)
@@ -41,6 +42,16 @@ async def render_text(
raise NotImplementedError
+@runtime_checkable
+class LinkPreviewWidget(Widget, Protocol):
+ @abstractmethod
+ async def render_link_preview(
+ self, data: dict, manager: DialogManager,
+ ) -> Optional[LinkPreviewOptions]:
+ """Create link preview."""
+ raise NotImplementedError
+
+
ButtonVariant = Union[InlineKeyboardButton, KeyboardButton]
RawKeyboard = list[list[ButtonVariant]]
diff --git a/src/aiogram_dialog/manager/message_manager.py b/src/aiogram_dialog/manager/message_manager.py
index f5836157..1d729e6d 100644
--- a/src/aiogram_dialog/manager/message_manager.py
+++ b/src/aiogram_dialog/manager/message_manager.py
@@ -129,10 +129,13 @@ def need_voice(self, new_message: NewMessage) -> bool:
def _message_changed(
self, new_message: NewMessage, old_message: OldMessage,
) -> bool:
- if new_message.text != old_message.text:
- return True
- # we cannot actually compare reply keyboards
- if new_message.reply_markup or old_message.has_reply_keyboard:
+ if (
+ (new_message.text != old_message.text) or
+ # we cannot actually compare reply keyboards
+ (new_message.reply_markup or old_message.has_reply_keyboard) or
+ # we do not know if link preview changed
+ new_message.link_preview_options
+ ):
return True
if self.had_media(old_message) != self.need_media(new_message):
@@ -349,6 +352,7 @@ async def edit_text(
reply_markup=new_message.reply_markup,
parse_mode=new_message.parse_mode,
disable_web_page_preview=new_message.disable_web_page_preview,
+ link_preview_options=new_message.link_preview_options,
)
async def edit_media(
@@ -395,6 +399,7 @@ async def send_text(self, bot: Bot, new_message: NewMessage) -> Message:
disable_web_page_preview=new_message.disable_web_page_preview,
reply_markup=new_message.reply_markup,
parse_mode=new_message.parse_mode,
+ link_preview_options=new_message.link_preview_options,
)
async def send_media(self, bot: Bot, new_message: NewMessage) -> Message:
diff --git a/src/aiogram_dialog/widgets/link_preview/__init__.py b/src/aiogram_dialog/widgets/link_preview/__init__.py
new file mode 100644
index 00000000..1d848cca
--- /dev/null
+++ b/src/aiogram_dialog/widgets/link_preview/__init__.py
@@ -0,0 +1,3 @@
+__all__ = ["LinkPreviewBase", "LinkPreview"]
+
+from .base import LinkPreview, LinkPreviewBase
diff --git a/src/aiogram_dialog/widgets/link_preview/base.py b/src/aiogram_dialog/widgets/link_preview/base.py
new file mode 100644
index 00000000..ac9f40ef
--- /dev/null
+++ b/src/aiogram_dialog/widgets/link_preview/base.py
@@ -0,0 +1,61 @@
+from typing import Optional
+
+from aiogram.types import LinkPreviewOptions
+
+from aiogram_dialog import DialogManager
+from aiogram_dialog.api.internal import LinkPreviewWidget, TextWidget
+from aiogram_dialog.widgets.common import BaseWidget, Whenable, WhenCondition
+
+
+class LinkPreviewBase(Whenable, BaseWidget, LinkPreviewWidget):
+ def __init__(self, when: WhenCondition = None):
+ super().__init__(when=when)
+
+ async def render_link_preview(
+ self, data: dict, manager: DialogManager,
+ ) -> Optional[LinkPreviewOptions]:
+ if not self.is_(data, manager):
+ return None
+ return await self._render_link_preview(data, manager)
+
+ async def _render_link_preview(
+ self, data: dict, manager: DialogManager,
+ ) -> Optional[LinkPreviewOptions]:
+ return None
+
+
+class LinkPreview(LinkPreviewBase):
+ def __init__(
+ self,
+ url: TextWidget,
+ is_disabled: bool = False,
+ prefer_small_media: bool = False,
+ prefer_large_media: bool = False,
+ show_above_text: bool = False,
+ when: WhenCondition = None,
+ ):
+ super().__init__(when=when)
+ self.url = url
+ self.is_disabled = is_disabled
+ self.prefer_small_media = prefer_small_media
+ self.prefer_large_media = prefer_large_media
+ self.show_above_text = show_above_text
+
+ async def render_link_preview(
+ self, data: dict, manager: DialogManager,
+ ) -> Optional[LinkPreviewOptions]:
+ if not self.is_(data, manager):
+ return None
+ return await self._render_link_preview(data, manager)
+
+ async def _render_link_preview(
+ self, data: dict, manager: DialogManager,
+ ) -> Optional[LinkPreviewOptions]:
+ url = await self.url.render_text(data, manager)
+ return LinkPreviewOptions(
+ url=url,
+ is_disabled=self.is_disabled,
+ prefer_small_media=self.prefer_small_media,
+ prefer_large_media=self.prefer_large_media,
+ show_above_text=self.show_above_text,
+ )
diff --git a/src/aiogram_dialog/widgets/utils.py b/src/aiogram_dialog/widgets/utils.py
index 16aa047d..4fd98b9f 100644
--- a/src/aiogram_dialog/widgets/utils.py
+++ b/src/aiogram_dialog/widgets/utils.py
@@ -2,16 +2,19 @@
from typing import Union
from aiogram_dialog.api.exceptions import InvalidWidgetType
-from aiogram_dialog.api.internal import DataGetter
+from aiogram_dialog.api.internal import DataGetter, LinkPreviewWidget
from .data.data_context import CompositeGetter, StaticGetter
from .input import BaseInput, CombinedInput, MessageHandlerFunc, MessageInput
from .kbd import Group, Keyboard
+from .link_preview import LinkPreviewBase
from .media import Media
from .text import Format, Multi, Text
from .widget_event import WidgetEventProcessor
-WidgetSrc = Union[str, Text, Keyboard, MessageHandlerFunc, Media, BaseInput]
+WidgetSrc = Union[
+ str, Text, Keyboard, MessageHandlerFunc, Media, BaseInput, LinkPreviewBase,
+]
SingleGetterBase = Union[DataGetter, dict]
GetterVariant = Union[
@@ -71,13 +74,26 @@ def ensure_media(widget: Union[Media, Sequence[Media]]) -> Media:
return Media()
+def ensure_link_preview(
+ widget: Union[LinkPreviewWidget, Sequence[LinkPreviewWidget]],
+) -> LinkPreviewWidget:
+ if isinstance(widget, LinkPreviewWidget):
+ return widget
+ if len(widget) > 1:
+ raise ValueError("Only one link preview widget is supported")
+ if len(widget) == 1:
+ return widget[0]
+ return LinkPreviewBase()
+
+
def ensure_widgets(
widgets: Sequence[WidgetSrc],
-) -> tuple[Text, Keyboard, Union[BaseInput, None], Media]:
+) -> tuple[Text, Keyboard, Union[BaseInput, None], Media, LinkPreviewWidget]:
texts = []
keyboards = []
inputs = []
media = []
+ link_preview = []
for w in widgets:
if isinstance(w, (str, Text)):
@@ -88,6 +104,8 @@ def ensure_widgets(
inputs.append(ensure_input(w))
elif isinstance(w, Media):
media.append(ensure_media(w))
+ elif isinstance(w, LinkPreviewBase):
+ link_preview.append(ensure_link_preview(w))
else:
raise InvalidWidgetType(
f"Cannot add widget of type {type(w)}. "
@@ -99,6 +117,7 @@ def ensure_widgets(
ensure_keyboard(keyboards),
ensure_input(inputs),
ensure_media(media),
+ ensure_link_preview(link_preview),
)
diff --git a/src/aiogram_dialog/window.py b/src/aiogram_dialog/window.py
index 832f30fc..c4eaf58c 100644
--- a/src/aiogram_dialog/window.py
+++ b/src/aiogram_dialog/window.py
@@ -5,6 +5,7 @@
from aiogram.types import (
UNSET_PARSE_MODE,
CallbackQuery,
+ LinkPreviewOptions,
Message,
)
from aiogram.types.base import UNSET_DISABLE_WEB_PAGE_PREVIEW
@@ -55,6 +56,7 @@ def __init__(
self.keyboard,
self.on_message,
self.media,
+ self.link_preview,
) = ensure_widgets(widgets)
self.getter = PreviewAwareGetter(
ensure_data_getter(getter),
@@ -87,6 +89,13 @@ async def render_kbd(
data, manager, keyboard,
)
+ async def render_link_preview(
+ self, data: dict, manager: DialogManager,
+ ) -> Optional[LinkPreviewOptions]:
+ if self.link_preview:
+ return await self.link_preview.render_link_preview(data, manager)
+ return None
+
async def load_data(
self, dialog: "DialogProtocol",
manager: DialogManager,
@@ -145,6 +154,9 @@ async def render(
parse_mode=self.parse_mode,
disable_web_page_preview=self.disable_web_page_preview,
media=await self.render_media(current_data, manager),
+ link_preview_options=await self.render_link_preview(
+ current_data, manager,
+ ),
)
except Exception:
logger.error("Cannot render window for state %s", self.state)
From bd56910a19d168b7c2758dc1b874ca180c385c15 Mon Sep 17 00:00:00 2001
From: chiri <2alivemafia@gmail.com>
Date: Mon, 16 Dec 2024 01:20:15 +0300
Subject: [PATCH 26/29] make `url` optional and add example for `LinkPreview`
widget
---
example/link_preview.py | 95 +++++++++++++++++++
.../widgets/link_preview/base.py | 5 +-
2 files changed, 97 insertions(+), 3 deletions(-)
create mode 100644 example/link_preview.py
diff --git a/example/link_preview.py b/example/link_preview.py
new file mode 100644
index 00000000..0ea3eed6
--- /dev/null
+++ b/example/link_preview.py
@@ -0,0 +1,95 @@
+from aiogram import Bot, Dispatcher
+from aiogram.filters import Command
+from aiogram.filters.state import State, StatesGroup
+from aiogram.fsm.storage.memory import MemoryStorage
+from aiogram.types import Message
+
+from aiogram_dialog import (
+ Dialog,
+ DialogManager,
+ StartMode,
+ Window,
+ setup_dialogs,
+)
+from aiogram_dialog.widgets.kbd import SwitchTo
+from aiogram_dialog.widgets.link_preview import LinkPreview
+from aiogram_dialog.widgets.text import Const, Format
+
+
+async def photo_getter(**_):
+ return {"photo_url": "https://nplus1.ru/news/2024/05/23/voyager-1-science-data"}
+
+
+class SG(StatesGroup):
+ MAIN = State()
+ IS_DISABLED = State()
+ SMALL_MEDIA = State()
+ LARGE_MEDIA = State()
+ SHOW_ABOVE_TEXT = State()
+
+
+BACK = SwitchTo(Const("back"), "_back", SG.MAIN)
+
+
+dialog = Dialog(
+ Window(
+ Format("Default\n{photo_url}"),
+ SwitchTo(
+ Const("disable"), "_disable", SG.IS_DISABLED,
+ ),
+ SwitchTo(
+ Const("prefer small media"), "_prefer_small_media", SG.SMALL_MEDIA,
+ ),
+ SwitchTo(
+ Const("prefer large media"), "_prefer_large_media", SG.LARGE_MEDIA,
+ ),
+ SwitchTo(
+ Const("show above text"), "_show_above_text", SG.SHOW_ABOVE_TEXT,
+ ),
+ getter=photo_getter,
+ state=SG.MAIN,
+ ),
+ Window(
+ Format("{photo_url}"),
+ LinkPreview(is_disabled=True),
+ BACK,
+ state=SG.IS_DISABLED,
+ getter=photo_getter,
+ ),
+ Window(
+ Const("prefer small media"),
+ LinkPreview(Format("{photo_url}"), prefer_small_media=True),
+ BACK,
+ state=SG.SMALL_MEDIA,
+ getter=photo_getter,
+ ),
+ Window(
+ Const("prefer large media"),
+ LinkPreview(Format("{photo_url}"), prefer_large_media=True),
+ BACK,
+ state=SG.LARGE_MEDIA,
+ getter=photo_getter,
+ ),
+ Window(
+ Const("show above text"),
+ LinkPreview(Format("{photo_url}"), show_above_text=True),
+ BACK,
+ state=SG.SHOW_ABOVE_TEXT,
+ getter=photo_getter,
+ ),
+)
+
+storage = MemoryStorage()
+bot = Bot("token")
+dp = Dispatcher(storage=storage)
+dp.include_router(dialog)
+setup_dialogs(dp)
+
+
+@dp.message(Command("start"))
+async def start(message: Message, dialog_manager: DialogManager):
+ await dialog_manager.start(SG.MAIN, mode=StartMode.RESET_STACK)
+
+
+if __name__ == "__main__":
+ dp.run_polling(bot, skip_updates=True)
diff --git a/src/aiogram_dialog/widgets/link_preview/base.py b/src/aiogram_dialog/widgets/link_preview/base.py
index ac9f40ef..7a2fe925 100644
--- a/src/aiogram_dialog/widgets/link_preview/base.py
+++ b/src/aiogram_dialog/widgets/link_preview/base.py
@@ -27,7 +27,7 @@ async def _render_link_preview(
class LinkPreview(LinkPreviewBase):
def __init__(
self,
- url: TextWidget,
+ url: Optional[TextWidget] = None,
is_disabled: bool = False,
prefer_small_media: bool = False,
prefer_large_media: bool = False,
@@ -51,9 +51,8 @@ async def render_link_preview(
async def _render_link_preview(
self, data: dict, manager: DialogManager,
) -> Optional[LinkPreviewOptions]:
- url = await self.url.render_text(data, manager)
return LinkPreviewOptions(
- url=url,
+ url=await self.url.render_text(data, manager) if self.url else None,
is_disabled=self.is_disabled,
prefer_small_media=self.prefer_small_media,
prefer_large_media=self.prefer_large_media,
From 22dd47b63479f12930d1f4c2cefa82d1a8b7f590 Mon Sep 17 00:00:00 2001
From: chiri <2alivemafia@gmail.com>
Date: Mon, 16 Dec 2024 02:18:15 +0300
Subject: [PATCH 27/29] add docs to LinkPreview widget
---
docs/conf.py | 5 +----
docs/widgets/index.rst | 8 +++++---
docs/widgets/link_preview/example.py | 27 +++++++++++++++++++++++++++
docs/widgets/link_preview/index.rst | 23 +++++++++++++++++++++++
4 files changed, 56 insertions(+), 7 deletions(-)
create mode 100644 docs/widgets/link_preview/example.py
create mode 100644 docs/widgets/link_preview/index.rst
diff --git a/docs/conf.py b/docs/conf.py
index 7a3178ad..c8410d17 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -13,13 +13,10 @@
# import os
# import sys
# sys.path.insert(0, os.path.abspath("."))
-
-import datetime
-
# -- Project information -----------------------------------------------------
project = "aiogram-dialog"
-copyright = f"{datetime.date.today().year}, Tishka17"
+copyright = "%Y, Tishka17"
author = "Tishka17"
master_doc = "index"
diff --git a/docs/widgets/index.rst b/docs/widgets/index.rst
index c11c0664..5678ef7a 100644
--- a/docs/widgets/index.rst
+++ b/docs/widgets/index.rst
@@ -4,13 +4,14 @@ Widgets and Rendering
Base information
********************
-Currently there are 4 kinds of widgets: :ref:`texts `, :ref:`keyboards `,
-:ref:`input `, :ref:`media` and you can create your own :ref:`widgets`.
+Currently there are 5 kinds of widgets: :ref:`texts `, :ref:`keyboards `,
+:ref:`input `, :ref:`media`, :ref:`link preview` and you can create your own :ref:`widgets`.
* **Texts** used to render text anywhere in dialog. It can be message text, button title and so on.
* **Keyboards** represent parts of ``InlineKeyboard``
* **Media** represent media attachment to message
* **Input** allows to process incoming messages from user. Is has no representation.
+* **Link Preview** used to manage link previews in messages.
Widgets can display static (e.g. ``Const``) and dynamic (e.g. ``Format``) content. To use dynamic data you have to set it. See :ref:`passing data `.
@@ -37,5 +38,6 @@ Also there are 2 general types:
keyboard/index
input/index
media/index
+ link_preview/index
hiding/index
- custom_widgets/index
+ custom_widgets/index
\ No newline at end of file
diff --git a/docs/widgets/link_preview/example.py b/docs/widgets/link_preview/example.py
new file mode 100644
index 00000000..3f9bbed4
--- /dev/null
+++ b/docs/widgets/link_preview/example.py
@@ -0,0 +1,27 @@
+from aiogram.filters.state import State, StatesGroup
+
+from aiogram_dialog import Window
+from aiogram_dialog.widgets.link_preview import LinkPreview
+from aiogram_dialog.widgets.text import Const
+
+
+class SG(StatesGroup):
+ MAIN = State()
+ SECOND = State()
+
+
+window = Window(
+ Const("https://nplus1.ru/news/2024/05/23/voyager-1-science-data"),
+ LinkPreview(is_disabled=True),
+ state=SG.MAIN,
+)
+
+second_window = Window(
+ Const("some text"),
+ LinkPreview(
+ url=Const("https://nplus1.ru/news/2024/05/23/voyager-1-science-data"),
+ prefer_small_media=True,
+ show_above_text=True,
+ ),
+ state=SG.MAIN,
+)
diff --git a/docs/widgets/link_preview/index.rst b/docs/widgets/link_preview/index.rst
new file mode 100644
index 00000000..0c552bfc
--- /dev/null
+++ b/docs/widgets/link_preview/index.rst
@@ -0,0 +1,23 @@
+.. _link_preview:
+
+LinkPreview
+*************
+
+The **LinkPreview** widget is used to manage link previews in messages.
+
+Parameters:
+
+* ``url``: A ``TextWidget`` with URL to be used in the link preview. If not provided, the first URL found in the message will be used.
+* ``is_disabled``: that controls whether the link preview is displayed. If ``True``, the preview will be disabled.
+* ``prefer_small_media``: that controls if the media in the link preview should be displayed in a smaller size. Ignored if media size change is not supported.
+* ``prefer_large_media``: that controls if the media in the link preview should be enlarged. Ignored if media size change is not supported.
+* ``show_above_text``: that specifies whether the link preview should be displayed above the message text. If ``True``, link preview be displayed above the message text.
+
+
+Code example:
+
+.. literalinclude:: ./example.py
+
+.. autoclass:: aiogram_dialog.widgets.link_preview.LinkPreview
+ :special-members: __init__
+ :members: render_link_preview, _render_link_preview
From 74d0d6e3b40d5b82c10a8896c25bc25965457159 Mon Sep 17 00:00:00 2001
From: Andrey Tikhonov <17@itishka.org>
Date: Mon, 16 Dec 2024 10:54:06 +0100
Subject: [PATCH 28/29] remove disable_web_page_preview usage, move example to
mega bot
---
example/link_preview.py | 95 -------------------
example/loading.py | 2 +
example/mega/bot.py | 2 +
example/mega/bot_dialogs/link_preview.py | 82 ++++++++++++++++
example/mega/bot_dialogs/main.py | 5 +
example/mega/bot_dialogs/states.py | 8 ++
.../api/entities/new_message.py | 1 -
src/aiogram_dialog/manager/message_manager.py | 3 -
src/aiogram_dialog/widgets/utils.py | 14 ++-
src/aiogram_dialog/window.py | 18 +++-
10 files changed, 124 insertions(+), 106 deletions(-)
delete mode 100644 example/link_preview.py
create mode 100644 example/mega/bot_dialogs/link_preview.py
diff --git a/example/link_preview.py b/example/link_preview.py
deleted file mode 100644
index 0ea3eed6..00000000
--- a/example/link_preview.py
+++ /dev/null
@@ -1,95 +0,0 @@
-from aiogram import Bot, Dispatcher
-from aiogram.filters import Command
-from aiogram.filters.state import State, StatesGroup
-from aiogram.fsm.storage.memory import MemoryStorage
-from aiogram.types import Message
-
-from aiogram_dialog import (
- Dialog,
- DialogManager,
- StartMode,
- Window,
- setup_dialogs,
-)
-from aiogram_dialog.widgets.kbd import SwitchTo
-from aiogram_dialog.widgets.link_preview import LinkPreview
-from aiogram_dialog.widgets.text import Const, Format
-
-
-async def photo_getter(**_):
- return {"photo_url": "https://nplus1.ru/news/2024/05/23/voyager-1-science-data"}
-
-
-class SG(StatesGroup):
- MAIN = State()
- IS_DISABLED = State()
- SMALL_MEDIA = State()
- LARGE_MEDIA = State()
- SHOW_ABOVE_TEXT = State()
-
-
-BACK = SwitchTo(Const("back"), "_back", SG.MAIN)
-
-
-dialog = Dialog(
- Window(
- Format("Default\n{photo_url}"),
- SwitchTo(
- Const("disable"), "_disable", SG.IS_DISABLED,
- ),
- SwitchTo(
- Const("prefer small media"), "_prefer_small_media", SG.SMALL_MEDIA,
- ),
- SwitchTo(
- Const("prefer large media"), "_prefer_large_media", SG.LARGE_MEDIA,
- ),
- SwitchTo(
- Const("show above text"), "_show_above_text", SG.SHOW_ABOVE_TEXT,
- ),
- getter=photo_getter,
- state=SG.MAIN,
- ),
- Window(
- Format("{photo_url}"),
- LinkPreview(is_disabled=True),
- BACK,
- state=SG.IS_DISABLED,
- getter=photo_getter,
- ),
- Window(
- Const("prefer small media"),
- LinkPreview(Format("{photo_url}"), prefer_small_media=True),
- BACK,
- state=SG.SMALL_MEDIA,
- getter=photo_getter,
- ),
- Window(
- Const("prefer large media"),
- LinkPreview(Format("{photo_url}"), prefer_large_media=True),
- BACK,
- state=SG.LARGE_MEDIA,
- getter=photo_getter,
- ),
- Window(
- Const("show above text"),
- LinkPreview(Format("{photo_url}"), show_above_text=True),
- BACK,
- state=SG.SHOW_ABOVE_TEXT,
- getter=photo_getter,
- ),
-)
-
-storage = MemoryStorage()
-bot = Bot("token")
-dp = Dispatcher(storage=storage)
-dp.include_router(dialog)
-setup_dialogs(dp)
-
-
-@dp.message(Command("start"))
-async def start(message: Message, dialog_manager: DialogManager):
- await dialog_manager.start(SG.MAIN, mode=StartMode.RESET_STACK)
-
-
-if __name__ == "__main__":
- dp.run_polling(bot, skip_updates=True)
diff --git a/example/loading.py b/example/loading.py
index baf0359b..52f3394f 100644
--- a/example/loading.py
+++ b/example/loading.py
@@ -17,6 +17,7 @@
setup_dialogs,
)
from aiogram_dialog.widgets.kbd import Button
+from aiogram_dialog.widgets.link_preview import LinkPreview
from aiogram_dialog.widgets.text import Const, Multi, Progress
API_TOKEN = os.getenv("BOT_TOKEN")
@@ -75,6 +76,7 @@ async def background(callback: CallbackQuery, manager: BaseDialogManager):
Window(
Const("Press button to start processing"),
Button(Const("Start"), id="start", on_click=start_bg),
+ LinkPreview(url=Const("http://ya.ru")),
state=MainSG.main,
),
)
diff --git a/example/mega/bot.py b/example/mega/bot.py
index 851342d3..7ba54e8a 100644
--- a/example/mega/bot.py
+++ b/example/mega/bot.py
@@ -11,6 +11,7 @@
from bot_dialogs.calendar import calendar_dialog
from bot_dialogs.counter import counter_dialog
from bot_dialogs.layouts import layouts_dialog
+from bot_dialogs.link_preview import link_preview_dialog
from bot_dialogs.main import main_dialog
from bot_dialogs.mutltiwidget import multiwidget_dialog
from bot_dialogs.reply_buttons import reply_kbd_dialog
@@ -68,6 +69,7 @@ async def on_unknown_intent(event: ErrorEvent, dialog_manager: DialogManager):
multiwidget_dialog,
switch_dialog,
reply_kbd_dialog,
+ link_preview_dialog,
)
diff --git a/example/mega/bot_dialogs/link_preview.py b/example/mega/bot_dialogs/link_preview.py
new file mode 100644
index 00000000..511be3e6
--- /dev/null
+++ b/example/mega/bot_dialogs/link_preview.py
@@ -0,0 +1,82 @@
+from aiogram_dialog import (
+ Dialog,
+ Window,
+)
+from aiogram_dialog.widgets.kbd import SwitchTo
+from aiogram_dialog.widgets.link_preview import LinkPreview
+from aiogram_dialog.widgets.text import Const, Format
+from . import states
+from .common import MAIN_MENU_BUTTON
+
+
+async def links_getter(**_):
+ return {
+ "main": "https://en.wikipedia.org/wiki/HTML_element",
+ "photo": "https://en.wikipedia.org/wiki/Hyperlink",
+ }
+
+
+LinkPreview_MAIN_MENU_BUTTON = SwitchTo(
+ text=Const("Back"), id="back", state=states.LinkPreview.MAIN,
+)
+COMMON_TEXT = Format(
+ "This is demo of different link preview options.\n"
+ "Link in text: {main}\n"
+ "Link in preview can be different\n\n"
+ "Current mode is:",
+)
+
+BACK = SwitchTo(Const("back"), "_back", states.LinkPreview.MAIN)
+
+link_preview_dialog = Dialog(
+ Window(
+ COMMON_TEXT,
+ Format("Default"),
+ SwitchTo(
+ Const("disable"), "_disable", states.LinkPreview.IS_DISABLED,
+ ),
+ SwitchTo(
+ Const("prefer small media"), "_prefer_small_media",
+ states.LinkPreview.SMALL_MEDIA,
+ ),
+ SwitchTo(
+ Const("prefer large media"), "_prefer_large_media",
+ states.LinkPreview.LARGE_MEDIA,
+ ),
+ SwitchTo(
+ Const("show above text"), "_show_above_text",
+ states.LinkPreview.SHOW_ABOVE_TEXT,
+ ),
+ MAIN_MENU_BUTTON,
+ state=states.LinkPreview.MAIN,
+ ),
+ Window(
+ COMMON_TEXT,
+ Const("is_disabled=True"),
+ LinkPreview(is_disabled=True),
+ LinkPreview_MAIN_MENU_BUTTON,
+ state=states.LinkPreview.IS_DISABLED,
+ ),
+ Window(
+ COMMON_TEXT,
+ Const("prefer_small_media=True"),
+ LinkPreview(Format("{photo}"), prefer_small_media=True),
+ LinkPreview_MAIN_MENU_BUTTON,
+ state=states.LinkPreview.SMALL_MEDIA,
+ ),
+ Window(
+ COMMON_TEXT,
+ Const("prefer_large_media=True"),
+ LinkPreview(Format("{photo}"), prefer_large_media=True),
+ LinkPreview_MAIN_MENU_BUTTON,
+ state=states.LinkPreview.LARGE_MEDIA,
+ ),
+ Window(
+ COMMON_TEXT,
+ Const("show_above_text=True"),
+ LinkPreview(Format("{photo}"), show_above_text=True),
+ LinkPreview_MAIN_MENU_BUTTON,
+ state=states.LinkPreview.SHOW_ABOVE_TEXT,
+ ),
+ getter=links_getter,
+)
diff --git a/example/mega/bot_dialogs/main.py b/example/mega/bot_dialogs/main.py
index 7305ddf5..0b541bf7 100644
--- a/example/mega/bot_dialogs/main.py
+++ b/example/mega/bot_dialogs/main.py
@@ -44,6 +44,11 @@
id="switch",
state=states.Switch.MAIN,
),
+ Start(
+ text=Const("🔗 Link Preview"),
+ id="linkpreview",
+ state=states.LinkPreview.MAIN,
+ ),
Start(
text=Const("⌨️ Reply keyboard"),
id="reply",
diff --git a/example/mega/bot_dialogs/states.py b/example/mega/bot_dialogs/states.py
index cb9d48a2..a18f1bd3 100644
--- a/example/mega/bot_dialogs/states.py
+++ b/example/mega/bot_dialogs/states.py
@@ -52,3 +52,11 @@ class Switch(StatesGroup):
MAIN = State()
INPUT = State()
LAST = State()
+
+
+class LinkPreview(StatesGroup):
+ MAIN = State()
+ IS_DISABLED = State()
+ SMALL_MEDIA = State()
+ LARGE_MEDIA = State()
+ SHOW_ABOVE_TEXT = State()
diff --git a/src/aiogram_dialog/api/entities/new_message.py b/src/aiogram_dialog/api/entities/new_message.py
index e360563a..6cc071cf 100644
--- a/src/aiogram_dialog/api/entities/new_message.py
+++ b/src/aiogram_dialog/api/entities/new_message.py
@@ -44,6 +44,5 @@ class NewMessage:
reply_markup: Optional[MarkupVariant] = None
parse_mode: Optional[str] = None
show_mode: ShowMode = ShowMode.AUTO
- disable_web_page_preview: Optional[bool] = None
media: Optional[MediaAttachment] = None
link_preview_options: Optional[LinkPreviewOptions] = None
diff --git a/src/aiogram_dialog/manager/message_manager.py b/src/aiogram_dialog/manager/message_manager.py
index 1d729e6d..2ad38c09 100644
--- a/src/aiogram_dialog/manager/message_manager.py
+++ b/src/aiogram_dialog/manager/message_manager.py
@@ -351,7 +351,6 @@ async def edit_text(
text=new_message.text,
reply_markup=new_message.reply_markup,
parse_mode=new_message.parse_mode,
- disable_web_page_preview=new_message.disable_web_page_preview,
link_preview_options=new_message.link_preview_options,
)
@@ -367,7 +366,6 @@ async def edit_media(
caption=new_message.text,
reply_markup=new_message.reply_markup,
parse_mode=new_message.parse_mode,
- disable_web_page_preview=new_message.disable_web_page_preview,
media=await self.get_media_source(new_message.media, bot),
**new_message.media.kwargs,
)
@@ -396,7 +394,6 @@ async def send_text(self, bot: Bot, new_message: NewMessage) -> Message:
text=new_message.text,
message_thread_id=new_message.thread_id,
business_connection_id=new_message.business_connection_id,
- disable_web_page_preview=new_message.disable_web_page_preview,
reply_markup=new_message.reply_markup,
parse_mode=new_message.parse_mode,
link_preview_options=new_message.link_preview_options,
diff --git a/src/aiogram_dialog/widgets/utils.py b/src/aiogram_dialog/widgets/utils.py
index 4fd98b9f..3da9d10a 100644
--- a/src/aiogram_dialog/widgets/utils.py
+++ b/src/aiogram_dialog/widgets/utils.py
@@ -1,5 +1,5 @@
from collections.abc import Callable, Sequence
-from typing import Union
+from typing import Union, Optional
from aiogram_dialog.api.exceptions import InvalidWidgetType
from aiogram_dialog.api.internal import DataGetter, LinkPreviewWidget
@@ -76,19 +76,25 @@ def ensure_media(widget: Union[Media, Sequence[Media]]) -> Media:
def ensure_link_preview(
widget: Union[LinkPreviewWidget, Sequence[LinkPreviewWidget]],
-) -> LinkPreviewWidget:
+) -> Optional[LinkPreviewWidget]:
if isinstance(widget, LinkPreviewWidget):
return widget
if len(widget) > 1:
raise ValueError("Only one link preview widget is supported")
if len(widget) == 1:
return widget[0]
- return LinkPreviewBase()
+ return None
def ensure_widgets(
widgets: Sequence[WidgetSrc],
-) -> tuple[Text, Keyboard, Union[BaseInput, None], Media, LinkPreviewWidget]:
+) -> tuple[
+ Text,
+ Keyboard,
+ Optional[BaseInput],
+ Media,
+ Optional[LinkPreviewWidget],
+]:
texts = []
keyboards = []
inputs = []
diff --git a/src/aiogram_dialog/window.py b/src/aiogram_dialog/window.py
index c4eaf58c..aeafd45a 100644
--- a/src/aiogram_dialog/window.py
+++ b/src/aiogram_dialog/window.py
@@ -1,3 +1,4 @@
+import warnings
from logging import getLogger
from typing import Any, Optional, cast
@@ -25,6 +26,7 @@
from .dialog import OnResultEvent
from .widgets.data import PreviewAwareGetter
from .widgets.kbd import Keyboard
+from .widgets.link_preview import LinkPreview
from .widgets.markup.inline_keyboard import InlineKeyboardFactory
from .widgets.utils import (
GetterVariant,
@@ -47,7 +49,7 @@ def __init__(
on_process_result: Optional[OnResultEvent] = None,
markup_factory: MarkupFactory = _DEFAULT_MARKUP_FACTORY,
parse_mode: Optional[str] = UNSET_PARSE_MODE,
- disable_web_page_preview: Optional[bool] = UNSET_DISABLE_WEB_PAGE_PREVIEW, # noqa: E501
+ disable_web_page_preview: Optional[bool] = None, # noqa: E501
preview_add_transitions: Optional[list[Keyboard]] = None,
preview_data: GetterVariant = None,
):
@@ -66,8 +68,19 @@ def __init__(
self.on_process_result = on_process_result
self.markup_factory = markup_factory
self.parse_mode = parse_mode
- self.disable_web_page_preview = disable_web_page_preview
self.preview_add_transitions = preview_add_transitions
+ if disable_web_page_preview is not None:
+ if self.link_preview:
+ raise ValueError(
+ "Cannot use LinkPreview widget "
+ "together with disable_web_page_preview",
+ )
+ warnings.warn(
+ "disable_web_page_preview is deprecated, "
+ "use `LinkPreview` widget instead",
+ category=DeprecationWarning,
+ )
+ self.link_preview = LinkPreview(is_disabled=True)
async def render_text(
self, data: dict, manager: DialogManager,
@@ -152,7 +165,6 @@ async def render(
text=await self.render_text(current_data, manager),
reply_markup=await self.render_kbd(current_data, manager),
parse_mode=self.parse_mode,
- disable_web_page_preview=self.disable_web_page_preview,
media=await self.render_media(current_data, manager),
link_preview_options=await self.render_link_preview(
current_data, manager,
From eacc7bcc7b47e4cf94a843cfad27c552768c6eb5 Mon Sep 17 00:00:00 2001
From: Andrey Tikhonov <17@itishka.org>
Date: Mon, 16 Dec 2024 17:37:57 +0100
Subject: [PATCH 29/29] Fix linter
---
example/mega/bot_dialogs/link_preview.py | 1 +
src/aiogram_dialog/widgets/link_preview/base.py | 6 +++++-
src/aiogram_dialog/widgets/utils.py | 2 +-
src/aiogram_dialog/window.py | 4 ++--
4 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/example/mega/bot_dialogs/link_preview.py b/example/mega/bot_dialogs/link_preview.py
index 511be3e6..d353fc43 100644
--- a/example/mega/bot_dialogs/link_preview.py
+++ b/example/mega/bot_dialogs/link_preview.py
@@ -5,6 +5,7 @@
from aiogram_dialog.widgets.kbd import SwitchTo
from aiogram_dialog.widgets.link_preview import LinkPreview
from aiogram_dialog.widgets.text import Const, Format
+
from . import states
from .common import MAIN_MENU_BUTTON
diff --git a/src/aiogram_dialog/widgets/link_preview/base.py b/src/aiogram_dialog/widgets/link_preview/base.py
index 7a2fe925..299b711b 100644
--- a/src/aiogram_dialog/widgets/link_preview/base.py
+++ b/src/aiogram_dialog/widgets/link_preview/base.py
@@ -52,7 +52,11 @@ async def _render_link_preview(
self, data: dict, manager: DialogManager,
) -> Optional[LinkPreviewOptions]:
return LinkPreviewOptions(
- url=await self.url.render_text(data, manager) if self.url else None,
+ url=(
+ await self.url.render_text(data, manager)
+ if self.url
+ else None
+ ),
is_disabled=self.is_disabled,
prefer_small_media=self.prefer_small_media,
prefer_large_media=self.prefer_large_media,
diff --git a/src/aiogram_dialog/widgets/utils.py b/src/aiogram_dialog/widgets/utils.py
index 3da9d10a..977d4984 100644
--- a/src/aiogram_dialog/widgets/utils.py
+++ b/src/aiogram_dialog/widgets/utils.py
@@ -1,5 +1,5 @@
from collections.abc import Callable, Sequence
-from typing import Union, Optional
+from typing import Optional, Union
from aiogram_dialog.api.exceptions import InvalidWidgetType
from aiogram_dialog.api.internal import DataGetter, LinkPreviewWidget
diff --git a/src/aiogram_dialog/window.py b/src/aiogram_dialog/window.py
index aeafd45a..035835dd 100644
--- a/src/aiogram_dialog/window.py
+++ b/src/aiogram_dialog/window.py
@@ -9,7 +9,6 @@
LinkPreviewOptions,
Message,
)
-from aiogram.types.base import UNSET_DISABLE_WEB_PAGE_PREVIEW
from aiogram_dialog.api.entities import (
EVENT_CONTEXT_KEY,
@@ -49,7 +48,7 @@ def __init__(
on_process_result: Optional[OnResultEvent] = None,
markup_factory: MarkupFactory = _DEFAULT_MARKUP_FACTORY,
parse_mode: Optional[str] = UNSET_PARSE_MODE,
- disable_web_page_preview: Optional[bool] = None, # noqa: E501
+ disable_web_page_preview: Optional[bool] = None,
preview_add_transitions: Optional[list[Keyboard]] = None,
preview_data: GetterVariant = None,
):
@@ -79,6 +78,7 @@ def __init__(
"disable_web_page_preview is deprecated, "
"use `LinkPreview` widget instead",
category=DeprecationWarning,
+ stacklevel=2,
)
self.link_preview = LinkPreview(is_disabled=True)