This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Title: Add ability to specify instance of contextvars context to Task() & asyncio.create_task()
Type: enhancement Stage: resolved
Components: asyncio Versions: Python 3.9, Python 3.8, Python 3.7
Status: closed Resolution: duplicate
Dependencies: Superseder: Accept explicit contextvars.Context in asyncio create_task() API
View: 46994
Assigned To: Nosy List: Jeff.Laughlin, asvetlov, msg555, yselivanov
Priority: normal Keywords: patch

Created on 2020-04-18 15:28 by Jeff.Laughlin, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 26664 closed msg555, 2021-06-11 06:41
Messages (2)
msg366722 - (view) Author: Jeff Laughlin (Jeff.Laughlin) Date: 2020-04-18 15:28
As a test engineer I want to be able to run async test fixtures and test cases in different async tasks with the same Context. Not a copy; the same specific instance of contextvars.Context().

I do NOT want the task to run in a COPY of the context because I want mutations to the context to be preserved so that I can pass the mutated context into another async task.

I do NOT want the task to inherit the potentially polluted global context.

class Task currently unconditionally copies the current global context and has no facility for the user to override the context.

Therefor I propose adding a context argument to the Task constructor and to create_task()

It should be noted that this argument should not be used for "normal" development and only for "weird" stuff like test frameworks.

I should also note that Context().run() is not useful here because it is not async and there is no obvious existing async equivalent. This proposal would be roughly equivalent.

I should also note that a hack like copying the items from one context to another will not work because it breaks ContextVar set/reset. I tried this. It was a heroic failure. It must be possible to run a task with an exist instance of context and not a copy.

Here is a real-world use case:

Here is the hacked Task constructor I cooked up:

class Task(asyncio.tasks._PyTask):
    def __init__(self, coro, *, loop=None, name=None, context=None):
        self._context = context if context is not None else copy_context()

        self._loop.call_soon(self.__step, context=self._context)

if folks are on board I can do a PR
msg415910 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2022-03-23 20:58
Duplicate of #46994
Date User Action Args
2022-04-11 14:59:29adminsetgithub: 84500
2022-03-23 20:58:50asvetlovsetstatus: open -> closed
superseder: Accept explicit contextvars.Context in asyncio create_task() API
messages: + msg415910

resolution: duplicate
stage: patch review -> resolved
2021-06-11 06:41:42msg555setkeywords: + patch
nosy: + msg555

pull_requests: + pull_request25251
stage: patch review
2020-04-18 15:28:07Jeff.Laughlincreate