Usage Tips¶
Here’s an unordered set of tips on how to use django-unasyncify
safely.
Use the async/sync variant naming scheme¶
When writing code, follow the following template for naming your functions that have sync and async variants
public functions |
private functions |
test functions |
|
sync |
|
|
|
async |
|
|
|
When function names are being unsyncified, three patterns being looked for are, based off the above naming pattern:
the names start with
test_async
(so the sync method should start withtest_
)the name starts with
_a
(so the sync method should start with_
)the name starts with
a
(so the sync method should just remove thata
)
Conditionally Include Code With IS_ASYNC
¶
IS_ASYNC
is a constant provided by the unasync helpers. It is True
, but when we run unasyncification we replace IS_ASYNC
to False
!
You can use this to do conditional behavior:
@generate_unasynced
async def arun_calculation(data):
result = {"used_async": IS_ASYNC}
if IS_ASYNC:
result["data"] = await third_party_lib.async_calc(data)
else:
result["data"] = another_third_party_lib.sync_calc(data)
return result
The above snippet will generate the following sync variant:
@from_codegen
def run_calculation(data):
result = {"used_async": False}
result["data"] = another_third_party_lib.sync_calc(data)
return result
A couple things to note in the above example:
IS_ASYNC
was replaced byFalse
the
if IS_ASYNC
branch in its entirety is simplified to only have theelse
case.
This can be a straightforward way to offer synced-ness branching, though it does mean that your coverage reports will not look great.
If coverage is a bigger issue here, then creating wrapper functions and calling that will also work:
def calculate(data):
return another_third_party_lib.sync_calc(data)
async def acalculate(data):
return await third_party_lib.async_calc(data)
@generate_unasynced
async def arun_calculation(data):
result = {"used_async": IS_ASYNC}
result["data"] = await acalculate(data)
return result
Here we have defined two functions that follow the sync/async variant patterns. Not here how I didn’t need to actually use the decorators, the naming convention is what is used.
With this our generated sync variant will look like:
@from_codegen
def run_calculation(data):
result = {"used_async": False}
result["data"] = calculate(data)
return result