leforestier/yattag

Unexpected result in async context

Trizalio opened this issue · 1 comments

Got unexpected result in async context, simplified example to reproduce:

import asyncio
from yattag import Doc
async def add_div_with_request_result(tag, text, url: str) -> None:
    with tag('div'):
        await asyncio.sleep(0.1)  # to emulate request delay 
        text(url)  # here goes result
async def main():
    doc, tag, text = Doc().tagtext()
    with tag('h1'):
        await asyncio.gather(
            add_div_with_request_result(tag, text, "http://some.com"),
            add_div_with_request_result(tag, text, "http://other.com")
        )
    print(doc.getvalue())
asyncio.run(main())

Expected result:

<h1><div>http://some.com<div></div>http://other.com</div></h1>

Actual result:

<h1><div><div>http://some.com</div>http://other.com</div></h1>

Hello,

I am not surprised with this result, this is the result I would expect from that piece of code.

I don't think it makes sense to try to asynchronously write to a yattag Doc instance. Think of it as writing to a file. You can write to a file asynchronously but then you should expect to get some lines mixed up.

My advice would be to first retrieve all the data you need (fetch these urls using asyncio.gather). And once you have all the data, you generate the yattag document synchronously.
In other words, first deal with business logic and only after that, deal with the presentation.