is semantically equivalent to::
manager = (EXPRESSION)
- aexit = type(manager).__aexit__
aenter = type(manager).__aenter__
+ aexit = type(manager).__aexit__
value = await aenter(manager)
hit_except = False
def __aenter__(self):
pass
+ body_executed = False
async def foo():
async with CM():
- pass
+ body_executed = True
with self.assertRaisesRegex(AttributeError, '__aexit__'):
run_async(foo())
+ self.assertFalse(body_executed)
def test_with_3(self):
class CM:
def __aexit__(self):
pass
+ body_executed = False
async def foo():
async with CM():
- pass
+ body_executed = True
with self.assertRaisesRegex(AttributeError, '__aenter__'):
run_async(foo())
+ self.assertFalse(body_executed)
def test_with_4(self):
class CM:
- def __enter__(self):
- pass
-
- def __exit__(self):
- pass
+ pass
+ body_executed = False
async def foo():
async with CM():
- pass
+ body_executed = True
- with self.assertRaisesRegex(AttributeError, '__aexit__'):
+ with self.assertRaisesRegex(AttributeError, '__aenter__'):
run_async(foo())
+ self.assertFalse(body_executed)
def test_with_5(self):
# While this test doesn't make a lot of sense,
--- /dev/null
+Improve the displayed error message when incorrect types are passed to ``async
+with`` statements by looking up the :meth:`__aenter__` special method before
+the :meth:`__aexit__` special method when entering an asynchronous context
+manager. Patch by Géry Ogam.
}
case TARGET(BEFORE_ASYNC_WITH): {
- _Py_IDENTIFIER(__aexit__);
_Py_IDENTIFIER(__aenter__);
-
+ _Py_IDENTIFIER(__aexit__);
PyObject *mgr = TOP();
- PyObject *exit = special_lookup(tstate, mgr, &PyId___aexit__),
- *enter;
+ PyObject *enter = special_lookup(tstate, mgr, &PyId___aenter__);
PyObject *res;
- if (exit == NULL)
+ if (enter == NULL) {
+ goto error;
+ }
+ PyObject *exit = special_lookup(tstate, mgr, &PyId___aexit__);
+ if (exit == NULL) {
+ Py_DECREF(enter);
goto error;
+ }
SET_TOP(exit);
- enter = special_lookup(tstate, mgr, &PyId___aenter__);
Py_DECREF(mgr);
- if (enter == NULL)
- goto error;
res = _PyObject_CallNoArg(enter);
Py_DECREF(enter);
if (res == NULL)
}
case TARGET(SETUP_WITH): {
- _Py_IDENTIFIER(__exit__);
_Py_IDENTIFIER(__enter__);
+ _Py_IDENTIFIER(__exit__);
PyObject *mgr = TOP();
PyObject *enter = special_lookup(tstate, mgr, &PyId___enter__);
PyObject *res;