I’ve identified a pattern for handling potentially-asynchronous callback functions in Python which I’m calling the await me maybe pattern.
It works by letting you return a value, a callable function that returns a value OR an awaitable function that returns that value.
I use this pattern in a bunch of different places in Datasette, so today I refactored that into a utility function :
1 import asyncio 2 3 async def await_me_maybe(value): 4 if callable(value): 5 value = value() 6 if asyncio.iscoroutine(value): 7 value = await value 8 return value
This commit includes a bunch of examples where this function is called, for example this code which gathers extra body scripts to be included at the bottom of the page:
The key trick here is that while you can’t use “await” inside a Python function that’s defined using “def name()” (rather than “async def name()” you CAN define “async def” inner functions within the function body
I came up with the name “await me maybe” in the shower today and couldn’t resist refactoring Datasette to add an await_me_maybe() utility function
Having been working in the Python async space for a while, I feel like we’ve generally seen an improvement in the maturity of the discourse around what can potentially be a divisive area.
In spaces I’ve been workin in it’s been a pleasure to work alongside the Django communities efforts, even if not directly within the Django community.
Having FastAPI succeed on top of Starlette has been similarly rewarding.
There’s such a mutually constructive attitude between the two different projects which makes it a pleasure to see a higher level framework take more of the spotlight, while working on the supporting scaffolding.
In short this is a call for the benefits of adopting a genuinely collaborative mindset rather than a competitive mindset.
We may all working on different little corners of the landscape, but we’re can still all appreciate that in the bigger view, we’re all working together.