Repository: aiogram/aiogram
Pull request #682 (2021-09-06 22:00:17)

Reworked handlers in use

codecov[bot]: # [Codecov](https://codecov.io/gh/aiogram/aiogram/pull/682?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram) Report
> Merging [#682](https://codecov.io/gh/aiogram/aiogram/pull/682?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram) (79d056a) into [dev-3.x](https://codecov.io/gh/aiogram/aiogram/commit/e356ede5decc5c5f7afae136b4f0105b79e2120d?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram) (e356ede) will **not change** coverage.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/aiogram/aiogram/pull/682/graphs/tree.svg?width=650&height=150&src=pr&token=cFqEr3p9MX&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram)](https://codecov.io/gh/aiogram/aiogram/pull/682?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram)

```diff
@@            Coverage Diff            @@
##           dev-3.x      #682   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          270       269    -1     
  Lines         5669      5664    -5     
=========================================
- Hits          5669      5664    -5     
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `100.00% <100.00%> (ø)` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/aiogram/aiogram/pull/682?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram) | Coverage Δ | |
|---|---|---|
| [aiogram/dispatcher/router.py](https://codecov.io/gh/aiogram/aiogram/pull/682/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aiogram#diff-YWlvZ3JhbS9kaXNwYXRjaGVyL3JvdXRlci5weQ==) | `100.00% <100.00%> (ø)` | |


Patch:
diff --git a/CHANGES/682.misc b/CHANGES/682.misc
new file mode 100644
index 00000000..a1a18c67
--- /dev/null
+++ b/CHANGES/682.misc
@@ -0,0 +1,1 @@
+Reworked **handlers_in_use** util. Function moved to Router as method **.resolve_used_update_types()**
diff --git a/aiogram/dispatcher/router.py b/aiogram/dispatcher/router.py
index b776bcdf..8f2df80b 100644
--- a/aiogram/dispatcher/router.py
+++ b/aiogram/dispatcher/router.py
@@ -1,7 +1,7 @@
 from __future__ import annotations
 
 import warnings
-from typing import Any, Dict, Generator, List, Optional, Union
+from typing import Any, Dict, Generator, List, Optional, Set, Union
 
 from ..types import TelegramObject
 from ..utils.imports import import_module
@@ -11,6 +11,8 @@ from .event.event import EventObserver
 from .event.telegram import TelegramEventObserver
 from .filters import BUILTIN_FILTERS
 
+INTERNAL_UPDATE_TYPES = frozenset({"update", "error"})
+
 
 class Router:
     """
@@ -91,6 +93,27 @@ class Router:
     def __repr__(self) -> str:
         return f"<{self}>"
 
+    def resolve_used_update_types(self, skip_events: Optional[Set[str]] = None) -> List[str]:
+        """
+        Resolve registered event names
+
+        Is useful for getting updates only for registered event types.
+
+        :param skip_events: skip specified event names
+        :return: set of registered names
+        """
+        handlers_in_use: Set[str] = set()
+        if skip_events is None:
+            skip_events = set()
+        skip_events = {*skip_events, *INTERNAL_UPDATE_TYPES}
+
+        for router in self.chain_tail:
+            for update_name, observer in router.observers.items():
+                if observer.handlers and update_name not in skip_events:
+                    handlers_in_use.add(update_name)
+
+        return list(sorted(handlers_in_use))
+
     async def propagate_event(self, update_type: str, event: TelegramObject, **kwargs: Any) -> Any:
         kwargs.update(event_router=self)
         observer = self.observers[update_type]
diff --git a/aiogram/utils/handlers_in_use.py b/aiogram/utils/handlers_in_use.py
deleted file mode 100644
index c1816476..00000000
--- a/aiogram/utils/handlers_in_use.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from itertools import chain
-from typing import List, cast
-
-from aiogram.dispatcher.dispatcher import Dispatcher
-from aiogram.dispatcher.router import Router
-
-INTERNAL_HANDLERS = [
-    "update",
-    "error",
-]
-
-
-def get_handlers_in_use(
-    dispatcher: Dispatcher, handlers_to_skip: List[str] = INTERNAL_HANDLERS
-) -> List[str]:
-    handlers_in_use: List[str] = []
-
-    for router in [dispatcher.sub_routers, dispatcher]:
-        if isinstance(router, list):
-            if router:
-                handlers_in_use.extend(chain(*list(map(get_handlers_in_use, router))))
-        else:
-            router = cast(Router, router)
-            for update_name, observer in router.observers.items():
-                if observer.handlers and update_name not in [*handlers_to_skip, *handlers_in_use]:
-                    handlers_in_use.append(update_name)
-
-    return handlers_in_use
diff --git a/examples/specify_updates.py b/examples/specify_updates.py
index 5877a33c..1ad3cd0f 100644
--- a/examples/specify_updates.py
+++ b/examples/specify_updates.py
@@ -5,7 +5,6 @@ from aiogram.dispatcher.router import Router
 from aiogram.types import CallbackQuery, ChatMemberUpdated, Message
 from aiogram.types.inline_keyboard_button import InlineKeyboardButton
 from aiogram.types.inline_keyboard_markup import InlineKeyboardMarkup
-from aiogram.utils.handlers_in_use import get_handlers_in_use
 
 TOKEN = "6wo"
 dp = Dispatcher()
@@ -33,7 +32,7 @@ async def chat_member_update(chat_member: ChatMemberUpdated, bot: Bot) -> None:
     await bot.send_message(
         chat_member.chat.id,
         "Member {chat_member.from_user.id} was changed "
-        + f"from {chat_member.old_chat_member.is_chat_member} to {chat_member.new_chat_member.is_chat_member}",
+        + f"from {chat_member.old_chat_member.status} to {chat_member.new_chat_member.status}",
     )
 
 
@@ -64,7 +63,7 @@ async def my_chat_member_change(chat_member: ChatMemberUpdated, bot: Bot) -> Non
     await bot.send_message(
         chat_member.chat.id,
         "Member was changed from "
-        + f"{chat_member.old_chat_member.is_chat_member} to {chat_member.new_chat_member.is_chat_member}",
+        + f"{chat_member.old_chat_member.status} to {chat_member.new_chat_member.status}",
     )
 
 
@@ -77,7 +76,7 @@ def main() -> None:
     dp.include_router(sub_router)
     dp.include_router(sub_sub_router)
 
-    useful_updates = get_handlers_in_use(dp)
+    useful_updates = dp.resolve_used_update_types()
 
     # And the run events dispatching
     dp.run_polling(bot, allowed_updates=useful_updates)


Test patch:
diff --git a/tests/test_dispatcher/test_dispatcher.py b/tests/test_dispatcher/test_dispatcher.py
index 520b190c..30f10970 100644
--- a/tests/test_dispatcher/test_dispatcher.py
+++ b/tests/test_dispatcher/test_dispatcher.py
@@ -29,7 +29,6 @@ from aiogram.types import (
     Update,
     User,
 )
-from aiogram.utils.handlers_in_use import get_handlers_in_use
 from tests.mocked_bot import MockedBot
 
 try:
@@ -737,30 +736,30 @@ class TestDispatcher:
         router21 = Router()
         router21.edited_message.register(simple_edited_msg_handler)
 
-        useful_updates1 = get_handlers_in_use(dispatcher)
+        useful_updates1 = dispatcher.resolve_used_update_types()
 
         assert sorted(useful_updates1) == sorted(["message"])
 
         dispatcher.include_router(router1)
 
-        useful_updates2 = get_handlers_in_use(dispatcher)
+        useful_updates2 = dispatcher.resolve_used_update_types()
 
         assert sorted(useful_updates2) == sorted(["message", "callback_query"])
 
         dispatcher.include_router(router2)
 
-        useful_updates3 = get_handlers_in_use(dispatcher)
+        useful_updates3 = dispatcher.resolve_used_update_types()
 
         assert sorted(useful_updates3) == sorted(["message", "callback_query", "poll"])
 
         router2.include_router(router21)
 
-        useful_updates4 = get_handlers_in_use(dispatcher)
+        useful_updates4 = dispatcher.resolve_used_update_types()
 
         assert sorted(useful_updates4) == sorted(
             ["message", "callback_query", "poll", "edited_message"]
         )
 
-        useful_updates5 = get_handlers_in_use(router2)
+        useful_updates5 = router2.resolve_used_update_types()
 
         assert sorted(useful_updates5) == sorted(["poll", "edited_message"])