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.

classification
Title: add constructor that support multiple context managers to contextlib.ExitStack and contextlib.AsyncExitStack
Type: enhancement Stage: resolved
Components: Library (Lib) Versions:
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: Nosy List: ZeD, iritkatriel, python-dev, serhiy.storchaka
Priority: normal Keywords: patch

Created on 2020-11-21 13:08 by ZeD, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 23444 closed python-dev, 2020-11-21 13:22
PR 23445 closed python-dev, 2020-11-21 13:31
Messages (3)
msg381561 - (view) Author: Vito De Tullio (ZeD) * Date: 2020-11-21 13:08
The enhancement is to add a __init__ method to both contextlib.ExitStack and contextlib.AsyncExitStack, so that you can pass (async)context managers directly in the costructor.

additionally, a new "context_managers" / "async_context_managers" field is added to retrieve the values passed


This will ease the usage with lists of context managers

instead of:

    with ExitStack() as stack:
        files = [stack.enter_context(open(fname)) for fname in filenames]

you can have

    with ExitStack(*(open(fname) for fname in filenames)) as stack:
        files = stack.context_managers

In my use case I have a fixed + variable number of (async)context managers, and I don't even need the "as" part

   ...
   in_send, in_receive = trio.open_memory_channel(0)
   out_sends, out_receives = [], []
   for _ in range(n): # n is dynamic
       out_send, out_receive = trio.open_memory_channel(0)
       out_sends.append(out_send)
       out_receives.append(out_receive)
   
   # syntax error
   async with in_send, in_receive, *out_sends, *out_receives:
       ...

   # with current AsyncExitStack
   async with AsyncExitStack() as stack:
       await stack.async_context_managers(in_send)
       await stack.async_context_managers(in_receive)
       for out_send in out_sends:
           await stack.async_context_managers(out_send)
       for out_receive in out_receives:
           await stack.async_context_managers(out_receives)
       ...

   # with the change
   async with AsyncExitStack(in_send, in_receive, *out_sends, *out_receives):
       ...
msg381564 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) Date: 2020-11-21 14:46
There used to be a contextlib.nested function which did this, and it was deprecated because there were problems with it. See here: https://docs.python.org/2/library/contextlib.html#contextlib.nested
msg381567 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2020-11-21 15:33
Yes, this design has an incorrigible flaw.
History
Date User Action Args
2022-04-11 14:59:38adminsetgithub: 86590
2020-11-21 15:33:34serhiy.storchakasetstatus: open -> closed

nosy: + serhiy.storchaka
messages: + msg381567

resolution: rejected
stage: patch review -> resolved
2020-11-21 14:46:23iritkatrielsetnosy: + iritkatriel
messages: + msg381564
2020-11-21 13:31:39python-devsetpull_requests: + pull_request22337
2020-11-21 13:22:53python-devsetkeywords: + patch
nosy: + python-dev

pull_requests: + pull_request22336
stage: patch review
2020-11-21 13:08:04ZeDcreate