Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-39037: Look up __enter__ before __exit__ in the with statement documentation #17608

Merged
merged 8 commits into from
Dec 30, 2019
54 changes: 40 additions & 14 deletions Doc/reference/compound_stmts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -399,10 +399,10 @@ The execution of the :keyword:`with` statement with one "item" proceeds as follo
#. The context expression (the expression given in the :token:`with_item`) is
evaluated to obtain a context manager.

#. The context manager's :meth:`__exit__` is loaded for later use.

#. The context manager's :meth:`__enter__` method is invoked.
geryogam marked this conversation as resolved.
Show resolved Hide resolved

#. The context manager's :meth:`__exit__` is loaded for later use.

#. If a target was included in the :keyword:`with` statement, the return value
from :meth:`__enter__` is assigned to it.

Expand Down Expand Up @@ -430,13 +430,36 @@ The execution of the :keyword:`with` statement with one "item" proceeds as follo
value from :meth:`__exit__` is ignored, and execution proceeds at the normal
location for the kind of exit that was taken.

The following code::

with expression as target:
suite

is semantically equivalent to::

manager = (expression)
value = type(manager).__enter__(manager)
geryogam marked this conversation as resolved.
Show resolved Hide resolved
exit = type(manager).__exit__
target = value
exception = False

try:
suite
except:
exception = True
if not exit(manager, *sys.exc_info()):
raise
finally:
if not exception:
exit(manager, None, None, None)

With more than one item, the context managers are processed as if multiple
:keyword:`with` statements were nested::

with A() as a, B() as b:
suite

is equivalent to ::
is semantically equivalent to::

with A() as a:
with B() as b:
Expand Down Expand Up @@ -811,23 +834,26 @@ able to suspend execution in its *enter* and *exit* methods.

The following code::

async with EXPR as VAR:
BLOCK
async with expression as target:
geryogam marked this conversation as resolved.
Show resolved Hide resolved
suite

Is semantically equivalent to::
is semantically equivalent to::

mgr = (EXPR)
aexit = type(mgr).__aexit__
aenter = type(mgr).__aenter__(mgr)
manager = (expression)
aexit = type(manager).__aexit__
value = type(manager).__aenter__(manager)
target = await value
exception = False

VAR = await aenter
try:
BLOCK
suite
except:
if not await aexit(mgr, *sys.exc_info()):
exception = True
if not await aexit(manager, *sys.exc_info()):
raise
else:
await aexit(mgr, None, None, None)
finally:
geryogam marked this conversation as resolved.
Show resolved Hide resolved
if not exception:
await aexit(manager, None, None, None)

See also :meth:`__aenter__` and :meth:`__aexit__` for details.

Expand Down