From 5276703f8e87572939095fbb1994721d1cd81937 Mon Sep 17 00:00:00 2001 From: Michael Krukov Date: Sat, 18 Apr 2020 20:10:16 +0300 Subject: [PATCH] Fixed bug with merging of different routers; Added test --- CHANGELOG.md | 6 ++++- docs/index.rst | 11 ++++++++ kutana/kutana.py | 2 +- kutana/router.py | 14 ++++++---- setup.py | 2 +- tests/test_router.py | 64 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 91 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f29082..35618d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Changelog -> Changes to public API is marked as `^` +> Changes to public API is marked as `^`. Possible changes to public API is marked as `^?`. + +- v4.1.6 + - ^? Fixed merging of 'different' routers + - Added tests for routers merges - v4.1.5 - Fixed `.send_message` with long messages. diff --git a/docs/index.rst b/docs/index.rst index 1f2588a..266da0c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -69,6 +69,17 @@ their methods for these classes in Full API. You can find descriptions of all possible "on_*" methods for adding your callbacks in :class:`kutana.plugin.Plugin` class. +Order of "on_*" methods +^^^^^^^^^^^^^^^^^^^^^^^ +Default order of processors: + +- on_any_message: 9 +- on_payload (vk): 7 +- on_commands: 6 +- on_attachments: 3 +- on_any_unprocessed_message: -3 +- Rest: ~0 + Attachments ^^^^^^^^^^^ diff --git a/kutana/kutana.py b/kutana/kutana.py index 8beba91..8474fb2 100644 --- a/kutana/kutana.py +++ b/kutana/kutana.py @@ -120,7 +120,7 @@ def _init_routers(self): def _add_router(new_router): for router in self._routers: - if isinstance(router, new_router.__class__): + if type(router) is type(new_router) and router.priority == new_router.priority: router.merge(new_router) return diff --git a/kutana/router.py b/kutana/router.py index 4871ad9..df2bdbe 100644 --- a/kutana/router.py +++ b/kutana/router.py @@ -16,6 +16,13 @@ def _key(self, handler): -handler.priority, ) + def _assert_routers_alike(self, other_router): + if type(other_router) is not type(self): + raise RuntimeError("Can't merge routers with different classes") + + if other_router.priority != self.priority: + raise RuntimeError("Can't merge routers with different priorities") + def _check_update(self, update, ctx): """Should update be processed?""" return True @@ -46,9 +53,7 @@ def add_handler(self, handler): self._handlers.add(handler) def merge(self, other_router): - if not isinstance(other_router, self.__class__): - raise RuntimeError("Can't merge routers with different classes") - + self._assert_routers_alike(other_router) self._handlers.update(other_router._handlers) async def handle(self, update, ctx): @@ -85,8 +90,7 @@ def add_handler(self, handler, key): self._handlers[key] = SortedList([handler], key=self._key) def merge(self, other_router): - if not isinstance(other_router, self.__class__): - raise RuntimeError("Can't merge routers with different classes") + self._assert_routers_alike(other_router) for key, handlers in other_router._handlers.items(): for handler in handlers: diff --git a/setup.py b/setup.py index ab8e7b2..3e77f53 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ import setuptools -VERSION = "4.1.5" +VERSION = "4.1.6" with open("README.md", "r") as fh: diff --git a/tests/test_router.py b/tests/test_router.py index 1409ae7..87aaff5 100644 --- a/tests/test_router.py +++ b/tests/test_router.py @@ -2,6 +2,7 @@ from kutana import Context from kutana.handler import Handler from kutana.router import Router, ListRouter, MapRouter +from kutana.routers import AnyMessageRouter, AnyUnprocessedMessageRouter def test_check(): @@ -52,3 +53,66 @@ def test_router_merge(): assert len(mr1._handlers["a"]) == 2 assert len(mr1._handlers["b"]) == 1 + + +def test_router_subclass_merge(): + mr1 = AnyMessageRouter() + mr2 = AnyUnprocessedMessageRouter() + mr3 = ListRouter() + mr4 = AnyMessageRouter() + + mr1.add_handler(Handler(1, "*", "*", 0)) + mr1.add_handler(Handler(2, "*", "*", 0)) + mr2.add_handler(Handler(3, "*", "*", 0)) + mr3.add_handler(Handler(4, "*", "*", 0)) + mr4.add_handler(Handler(5, "*", "*", 0)) + + with pytest.raises(RuntimeError): + mr1.merge(mr2) + + with pytest.raises(RuntimeError): + mr1.merge(mr3) + + with pytest.raises(RuntimeError): + mr2.merge(mr3) + + mr4.merge(mr1) + + assert len(mr1._handlers) == 2 + assert len(mr2._handlers) == 1 + assert len(mr3._handlers) == 1 + assert len(mr4._handlers) == 3 + assert set(map(lambda h: h.handle, mr4._handlers)) == {5, 1, 2} + + +def test_router_merge_priority(): + mr1 = AnyMessageRouter(priority=9) + mr2 = AnyMessageRouter(priority=7) + mr3 = AnyMessageRouter(priority=5) + mr4 = AnyMessageRouter(priority=5) + + mr1.add_handler(Handler(1, "*", "*", 0)) + mr2.add_handler(Handler(2, "*", "*", 0)) + mr3.add_handler(Handler(3, "*", "*", 0)) + mr3.add_handler(Handler(4, "*", "*", 5)) + mr4.add_handler(Handler(5, "*", "*", 3)) + mr4.add_handler(Handler(6, "*", "*", 10)) + + with pytest.raises(RuntimeError): + mr1.merge(mr2) + + with pytest.raises(RuntimeError): + mr1.merge(mr3) + + with pytest.raises(RuntimeError): + mr2.merge(mr3) + + mr3.merge(mr4) + + handlers = list(map(lambda h: h.handle, [ + *mr1._handlers, + *mr2._handlers, + *mr3._handlers, + ])) + + assert handlers == [1, 2, 6, 4, 5, 3]