Skip to content

fix: support sync handlers in inject and auto_inject - #46

Merged
lesnik512 merged 1 commit into
mainfrom
fix/sync-handlers-44
Oct 17, 2026
Merged

lesnik512 merged 1 commit into
mainfrom
fix/sync-handlers-44

Conversation

@lesnik512

Copy link
Copy Markdown
Member

Closes #44

inject now returns a sync wrapper for a function that is not a coroutine function and an async wrapper otherwise, the same split modern-di-flask has used since 4.1.0. Both wrappers find the per-update child container in the handler kwargs and resolve FromDI parameters from it the same way.

Before this change the wrapper was always async def. With @inject on a sync handler, aiogram saw a coroutine function, awaited the wrapper, and the wrapper then awaited the handler's None return value and raised TypeError. Under auto_inject=True, the router walk swapped in the async wrapper but left HandlerObject.awaitable as False, so aiogram ran the wrapper in a thread and dropped the coroutine. The handler never ran.

The router walk now copies awaitable and varkw from the rebuilt HandlerObject along with callback and params, so every field aiogram derives from the callback matches the new one.

Typing: inject is now Callable[..., T] -> Callable[..., T], the same signature modern-di-flask uses. An async function's T is its coroutine type, so the return type follows the input without overloads.

modern_di_aiogram.dialog.inject is unchanged. aiogram-dialog awaits every getter and callback (Dialog._process_callback, SimpleEventProcessor.process_event, Dialog.load_data), so it does not support sync callbacks with or without this package. A sync wrapper there would fail the same way the async one does.

Tests added, all failing before the fix:

  • a sync handler under auto_inject runs and gets its dependency, with warnings raised as errors so a "never awaited" warning fails the test
  • HandlerObject.awaitable matches the swapped callback for both sync and async handlers after auto_inject
  • @inject on a sync handler runs it once and gets its dependency
  • @inject on a sync handler forwards a declared modern_di_container parameter
  • inject returns a coroutine function only for coroutine functions

The existing async tests cover the unchanged async behavior. README now says sync handlers are supported.

The **kwargs parameter-order bug (#45) is not touched here.

@lesnik512
lesnik512 merged commit f30a329 into main Oct 17, 2026
12 checks passed
@lesnik512
lesnik512 deleted the fix/sync-handlers-44 branch October 17, 2026 09:59
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.

Sync handlers break with inject: auto_inject never runs them, @inject raises after the body

1 participant