Transform ID:Documentation Index
Fetch the complete documentation index at: https://docs.refactron.dev/llms.txt
Use this file to discover all available pages before exploring further.
callback_to_async_await
Language: Python
What it does
Detects functions whose last positional parameter is a callback (namedcallback, cb, or done) that is invoked exactly once at the tail of every control-flow branch. Rewrites the function as async def, drops the callback parameter, and returns what the callback was being passed.
Detector pattern
The detector lives atsrc/analyze/detectors/python/callback-pattern.ts. It scans for def statements where the last positional parameter name matches the callback alias set, then walks the function body to verify the call shape.
Preconditions
- The callback parameter is the last positional parameter of the function.
- The function is not already async (
async def). - The function is not a generator (no
yield/yield from). - The callback is invoked exactly once, on the tail of every reachable branch.
- Cross-file: no external file imports this function and passes a callback at the call site (would orphan that caller). The transform skips itself when an
import <module>followed by<module>.<fn>(... cb)orfrom <module> import <fn>followed by<fn>(... cb)is found in the project.
Before / after
Edge cases handled
- Callback aliases:
callback,cb,done. - Preserves preceding decorators (e.g.
@retry). - Preserves type hints on the remaining parameters.
Edge cases NOT handled (skip via precondition)
- Callback is not the last positional parameter (e.g.
def f(callback, x)). - Function is a generator (
yield). - Callback is called more than once (multiple branches each invoking it).
- Function is already declared
async. - An external file in the project calls this function passing a callback argument.
Actual emitted form may differ slightly per the transform’s idempotency rules — run
refactron run --dry-run to see the exact diff for your code.