Skip to content

Support for async with #1179

@ikappaki

Description

@ikappaki

Hi,

Python provides async with to with asynchronous context managers, it's like async but for asynchronous operations

For example, given the below file defining and calling with on an async context manager

awith.py

import asyncio

class AsyncContextManager:
    async def __aenter__(self):
        print("Entering")
        return self

    async def __aexit__(self, exc_type, exc, tb):
        print("Exiting")

async def main():
    async with AsyncContextManager() as manager:
        print("Inside")

if __name__ == "__main__":
    asyncio.run(main())

the output is

> python .\awith.py
Entering
Inside
Exiting

A simple with of course won't work in Basilisp
issuefor.lpy

(import asyncio awith)

(defasync main
  []
  (with [_ (awith/AsyncContextManager)]
        (println "inside")))

(asyncio/run (main))

it throws an error

> basilisp run .issuefor.lpy
Traceback (most recent call last):
  File "C:\\issuefor.lpy", line 6, in main
    (println "inside")))
              ^^^^^^^^^
AttributeError: 'AsyncContextManager' object has no attribute '__enter__'. Did you mean: '__aenter__'?

A naive work around is to directly call the manager enter/exit functions:

(defasync main
  []
  (let [acm (awith/AsyncContextManager)]
    (try
      (await (.__aenter__ acm))
      (println "inside")
      (finally
        (await (.__aexit__ acm nil nil nil))))))

Could support for async with be added? One possible approach might be to specify an :async meta key in the with metadata, as in (^:async with [...] ...).

Thanks

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions