Skip to content

Detect async callable objects as awaitable handlers - #1858

Open
Sanjays2402 wants to merge 1 commit into
aiogram:dev-3.xfrom
Sanjays2402:fix/async-callable-object-detection
Open

Detect async callable objects as awaitable handlers#1858
Sanjays2402 wants to merge 1 commit into
aiogram:dev-3.xfrom
Sanjays2402:fix/async-callable-object-detection

Conversation

@Sanjays2402

Copy link
Copy Markdown

Description

CallableObject.__post_init__ decided awaitability with inspect.iscoroutinefunction(callback), which is False for an instance of a class whose __call__ is a coroutine function. Such handlers/filters were therefore dispatched through asyncio.to_thread(), so calling them just returned an un-awaited coroutine ("coroutine was never awaited") and the handler body never ran. Awaitability now also considers type(callback).__call__, matching how Filter subclasses were already special-cased.

Note: the issue also mentions lambdas that return a coroutine. That is a plain sync function whose return value happens to be awaitable, which cannot be detected by introspection, so this PR intentionally only covers async callable objects.

Fixes #1721

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?

  • New test_call_async_callable_object and the extended test_init_awaitable parametrization fail on dev-3.x (never-awaited coroutine returned) and pass with the fix.
  • pytest tests/test_dispatcher — 133 passed, 1 skipped.

Test Configuration:

  • Operating System: macOS
  • Python version: 3.14

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

CallableObject determined awaitability with inspect.iscoroutinefunction()
on the callback itself, which is False for an instance of a class whose
__call__ is a coroutine function. Such handlers and filters were run via
asyncio.to_thread(), so calling them returned an un-awaited coroutine and
Python emitted 'coroutine was never awaited'; the handler body never ran.

Awaitability now also considers type(callback).__call__, matching how
Filter subclasses were already special-cased.

Adds regression coverage asserting both the awaitable flag and that the
call is actually awaited.

Closes aiogram#1721
@github-actions

Copy link
Copy Markdown

❌ Changelog is required!

You need to add a brief description of the changes to the CHANGES directory.

Changes file should be named like <issue or PR number>.<category>.rst,
example 1234.bugfix.rst where 1234 is the PR or issue number and bugfix is the category.

The content of the file should be a brief description of the changes in
the PR in the format of a description of what has been done.

Possible categories are: feature, bugfix, doc, removal and misc.

@github-actions github-actions Bot added the 3.x Issue or PR for stable 3.x version label Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3.x Issue or PR for stable 3.x version

Projects

None yet

Development

Successfully merging this pull request may close these issues.

lambdas and callable objects are not recognized as awaitable handlers

1 participant