I was reading the following doc and got confused.
https://docs.python.org/3.7/reference/datamodel.html#object.__aenter__
According to the API doc itself (and original PEP 492), __aenter__() "is semantically similar to the __enter__(), with only difference that it must return an awaitable." __aexit__() has similar sentence that confuses me too.
PEP 492 also implies the (awaitable) object returned from obj.__aenter__() will be awaited immediately. In same manner, the (awaitable) object returned from obj.__aexit__() will be awaited too.
(From PEP 492)
> async with EXPR as VAR:
> BLOCK
>
> which is semantically equivalent to:
>
> mgr = (EXPR)
> aexit = type(mgr).__aexit__
> aenter = type(mgr).__aenter__(mgr)
> exc = True
>
> VAR = await aenter
> try:
> BLOCK
> except:
> if not await aexit(mgr, *sys.exc_info()):
> raise
> else:
> await aexit(mgr, None, None, None)
On the other hand, actual CPython implementation won't do that; it won't await the returned objects.
Moreover, the example shown in the API doc (AsyncContextManager) does NOT return awaitable as the doc itself suggests, but just await inside __aenter__() (and __aexit__()).
> class AsyncContextManager:
> async def __aenter__(self):
> await log('entering context')
>
> async def __aexit__(self, exc_type, exc, tb):
> await log('exiting context')
I'm not sure which is true; the doc saying "__aenter__() must return awaitable" is just incorrect, or CPython implementation has a bug. Actual source implies former. _ContextManagerMixin in asyncio.locks does not return awaitable at all, for example.
Anyway, I believe there are inconsistencies around here.
|