Skip to content

feat: вложенные роутеры с наследованием middleware и фильтров#63

Merged
love-apples merged 8 commits intolove-apples:mainfrom
MWT-proger:main
Apr 1, 2026
Merged

feat: вложенные роутеры с наследованием middleware и фильтров#63
love-apples merged 8 commits intolove-apples:mainfrom
MWT-proger:main

Conversation

@MWT-proger
Copy link
Copy Markdown
Contributor

Closes #62

Что сделано

Реализована поддержка вложенных роутеров — хендлеры дочерних роутеров
теперь видны диспетчеру и наследуют middleware и фильтры всех родителей
по цепочке вложенности на любую глубину.

Изменения

maxapi/dispatcher.py

  • _iter_routers() — новый генератор рекурсивного обхода дерева роутеров.
    Для каждого роутера накапливает от всех предков:
    middlewares, filters (MagicFilter), base_filters (BaseFilter).
    Dispatcher (self) исключён из накопления — его middleware применяется
    глобально через global_chain.

  • _check_router_filters() — принимает готовые накопленные списки
    фильтров вместо объекта роутера.

  • _prepare_handlers() — переведён на _iter_routers, вложенные
    роутеры получают bot и обрабатываются через extract_commands.

  • handle_raw_response() — переведён на _iter_routers.

  • _process_event() — использует _iter_routers; роутеры без
    совпадающих хендлеров пропускаются, что исключает лишние запуски
    middleware для «пустых» посещений.

tests/test_nested_routers.py

27 новых тестов в 5 классах:

Класс Что проверяет
TestIterRouters unit: накопление middleware / filters / base_filters, изоляция соседей
TestNestedRouterDispatch вызов хендлеров на 2-м и 3-м уровне, приоритет родителя
TestNestedMiddlewareInheritance порядок оборачивания на 3 уровнях, изоляция соседних роутеров
TestNestedBaseFilterInheritance блокировка/пропуск на каждом уровне, инъекция данных из фильтра
TestNestedMagicFilterInheritance F.xxx на 3 уровнях вложенности

Пример использования

dp = Dispatcher()

parent = Router()
parent.middleware(AuthMiddleware())
parent.filter(IsAdminFilter())

child = Router()

@child.message_created()
async def handler(event):
    ...  # AuthMiddleware и IsAdminFilter уже применены

parent.include_routers(child)
dp.include_routers(parent)

…ware и фильтров

Добавлен рекурсивный обход дерева роутеров через _iter_routers:
дочерние роутеры автоматически наследуют middleware, MagicFilter и BaseFilter
от всех родителей по цепочке вложенности.
Покрыто тестами: unit на _iter_routers, интеграционные на dispatch,
наследование middleware (3+ уровня), BaseFilter и MagicFilter.
@MWT-proger
Copy link
Copy Markdown
Contributor Author

@love-apples Посмотришь как будет время ?

Copy link
Copy Markdown
Contributor

@Olegt0rr Olegt0rr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Хороший PR, но требует небольших доработок по указанным проблемам

@love-apples
Copy link
Copy Markdown
Owner

@MWT-proger привет! Внеси, пожалуйста, правки

@MWT-proger
Copy link
Copy Markdown
Contributor Author

@love-apples привет, сейчас этим как раз занимаюсь.
@Olegt0rr спасибо за качественное ревью, полезные комментарии. Скоро залью обновление.

Вынесен обход уникальных экземпляров роутеров в _iter_unique_routers и применён в _prepare_handlers, _process_event и handle_raw_response, чтобы один и тот же роутер не обрабатывал событие дважды. При подготовке обработчиков добавлено предупреждение в лог о повторных включениях. Добавлены тесты на дедупликацию и логирование.
Метод возвращает только dict (включая {}) или False, поэтому убрано | None из аннотации и обновлён Returns в докстринге.
Добавлен обход с path по текущей ветви DFS: повторный заход в роутер на цикле пропускается, после обхода поддерева ключ снимается из path. Добавлен тест, что при a↔b полный обход конечен и даёт оба роутера.
…ёх уровней

Добавлены сценарии с накопленными фильтрами: сначала не-бот, затем «админский» user_id; события задаются через мок sender с полями как у User. Покрыты случаи обоих совпадений и блокировки на r1 или r2.
@MWT-proger MWT-proger requested a review from Olegt0rr March 25, 2026 18:09
Разбиты длинные строки в докстрингах _iter_routers и _iter_unique_routers; в тестах MagicFilter заменено сравнение is_bot с False на ~F; укорочены имена длинных тестов и модульный docstring.
…andlers

В _iter_routers отключён спуск в поддерево Dispatcher-self, чтобы корневые роутеры не обходились повторно через dp.routers и не давали ложные warning о повторных включениях. Добавлен регрессионный тест на отсутствие такого warning при уникальных корневых роутерах.
@MWT-proger
Copy link
Copy Markdown
Contributor Author

@love-apples @Olegt0rr привет, Посмотрите ?

@love-apples love-apples merged commit 6cfc497 into love-apples:main Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Вложенные роутеры не видны диспетчеру и не наследуют middleware и фильтры родителей

3 participants