diff --git a/dominate/dom_tag.py b/dominate/dom_tag.py index b3becf5..18f62b7 100644 --- a/dominate/dom_tag.py +++ b/dominate/dom_tag.py @@ -23,7 +23,7 @@ from collections import defaultdict, namedtuple from functools import wraps import threading -from asyncio import get_running_loop +from asyncio import current_task, get_running_loop from uuid import uuid4 from contextvars import ContextVar @@ -73,7 +73,8 @@ def _get_thread_context(): try: if get_running_loop().is_running(): # Only add this extra information if we are actually in a running event loop - context.append(("async", _get_async_context_id())) + # A child task inherits ContextVars, so its task identity must also differ. + context.append(("async", _get_async_context_id(), current_task())) # A runtime error is raised if there is no async loop... except RuntimeError: pass diff --git a/tests/test_dom_tag_async.py b/tests/test_dom_tag_async.py index 92c2438..6d2dd74 100644 --- a/tests/test_dom_tag_async.py +++ b/tests/test_dom_tag_async.py @@ -1,10 +1,31 @@ -from asyncio import gather, run, Semaphore +from asyncio import create_task, gather, run, Semaphore from textwrap import dedent from dominate import tags from dominate.dom_tag import async_context_id +def test_child_task_does_not_inherit_parent_dom_context(): + async def build_child(): + with tags.div(id='child') as child: + tags.span('child content') + return str(child) + + async def build_parent(): + with tags.div(id='parent') as parent: + child = await create_task(build_child()) + return str(parent), child + + token = async_context_id.set(None) + try: + parent, child = run(build_parent()) + finally: + async_context_id.reset(token) + + assert parent == '
' + assert child == '