mirror of
https://github.com/python/cpython.git
synced 2026-01-06 15:32:22 +00:00
bpo-39037: Fix lookup order of magic methods in with statement documentation (GH-17608)
* __enter__ is now looked up before __exit__ to give a more intuitive error message * add pseudo-code equivalent for the with statement * fix pseudo-code for the async with statement to use a finally clause * use SUITE rather than BLOCK for consistency with the language grammar Patch by Géry Ogam.
This commit is contained in:
parent
32a12aed6d
commit
226e6e7d43
1 changed files with 49 additions and 18 deletions
|
|
@ -399,6 +399,8 @@ 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:`__enter__` is loaded for later use.
|
||||
|
||||
#. The context manager's :meth:`__exit__` is loaded for later use.
|
||||
|
||||
#. The context manager's :meth:`__enter__` method is invoked.
|
||||
|
|
@ -430,17 +432,41 @@ 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)
|
||||
enter = type(manager).__enter__
|
||||
exit = type(manager).__exit__
|
||||
value = enter(manager)
|
||||
hit_except = False
|
||||
|
||||
try:
|
||||
TARGET = value
|
||||
SUITE
|
||||
except:
|
||||
hit_except = True
|
||||
if not exit(manager, *sys.exc_info()):
|
||||
raise
|
||||
finally:
|
||||
if not hit_except:
|
||||
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
|
||||
SUITE
|
||||
|
||||
is equivalent to ::
|
||||
is semantically equivalent to::
|
||||
|
||||
with A() as a:
|
||||
with B() as b:
|
||||
suite
|
||||
SUITE
|
||||
|
||||
.. versionchanged:: 3.1
|
||||
Support for multiple context expressions.
|
||||
|
|
@ -772,24 +798,25 @@ iterators.
|
|||
The following code::
|
||||
|
||||
async for TARGET in ITER:
|
||||
BLOCK
|
||||
SUITE
|
||||
else:
|
||||
BLOCK2
|
||||
SUITE2
|
||||
|
||||
Is semantically equivalent to::
|
||||
|
||||
iter = (ITER)
|
||||
iter = type(iter).__aiter__(iter)
|
||||
running = True
|
||||
|
||||
while running:
|
||||
try:
|
||||
TARGET = await type(iter).__anext__(iter)
|
||||
except StopAsyncIteration:
|
||||
running = False
|
||||
else:
|
||||
BLOCK
|
||||
SUITE
|
||||
else:
|
||||
BLOCK2
|
||||
SUITE2
|
||||
|
||||
See also :meth:`__aiter__` and :meth:`__anext__` for details.
|
||||
|
||||
|
|
@ -811,23 +838,27 @@ able to suspend execution in its *enter* and *exit* methods.
|
|||
|
||||
The following code::
|
||||
|
||||
async with EXPR as VAR:
|
||||
BLOCK
|
||||
async with EXPRESSION as TARGET:
|
||||
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__
|
||||
aenter = type(manager).__aenter__
|
||||
value = await aenter(manager)
|
||||
hit_except = False
|
||||
|
||||
VAR = await aenter
|
||||
try:
|
||||
BLOCK
|
||||
TARGET = value
|
||||
SUITE
|
||||
except:
|
||||
if not await aexit(mgr, *sys.exc_info()):
|
||||
hit_except = True
|
||||
if not await aexit(manager, *sys.exc_info()):
|
||||
raise
|
||||
else:
|
||||
await aexit(mgr, None, None, None)
|
||||
finally:
|
||||
if not hit_except:
|
||||
await aexit(manager, None, None, None)
|
||||
|
||||
See also :meth:`__aenter__` and :meth:`__aexit__` for details.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue