How can async support dispatch between sync and async variants of the same code?

I should probably add how this is used.

For the library developer, you just add @add_sync_version to those (public) async functions and methods for which you want to add a sync version. E.g.

@add_sync_version
async def spam(): ...

For the user of the library, if they want the async version they can just write

    x = await spam()

If they want the sync version they can write

    x = spam.sync()