summaryrefslogtreecommitdiffstats
path: root/Lib/contextlib.py
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2021-06-29 08:28:15 (GMT)
committerGitHub <noreply@github.com>2021-06-29 08:28:15 (GMT)
commit6cb145d23f5cf69b6d7414877d142747cd3d134c (patch)
tree0617efcd6911c14a1b8003bb9bee5fc68e521103 /Lib/contextlib.py
parent20a88004bae8ead66a205a125e1fe979376fc3ea (diff)
downloadcpython-6cb145d23f5cf69b6d7414877d142747cd3d134c.zip
cpython-6cb145d23f5cf69b6d7414877d142747cd3d134c.tar.gz
cpython-6cb145d23f5cf69b6d7414877d142747cd3d134c.tar.bz2
bpo-44471: Change error type for bad objects in ExitStack.enter_context() (GH-26820)
A TypeError is now raised instead of an AttributeError in ExitStack.enter_context() and AsyncExitStack.enter_async_context() for objects which do not support the context manager or asynchronous context manager protocols correspondingly.
Diffstat (limited to 'Lib/contextlib.py')
-rw-r--r--Lib/contextlib.py23
1 files changed, 17 insertions, 6 deletions
diff --git a/Lib/contextlib.py b/Lib/contextlib.py
index 1a8ef61..004d103 100644
--- a/Lib/contextlib.py
+++ b/Lib/contextlib.py
@@ -473,9 +473,14 @@ class _BaseExitStack:
"""
# We look up the special methods on the type to match the with
# statement.
- _cm_type = type(cm)
- _exit = _cm_type.__exit__
- result = _cm_type.__enter__(cm)
+ cls = type(cm)
+ try:
+ _enter = cls.__enter__
+ _exit = cls.__exit__
+ except AttributeError:
+ raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does "
+ f"not support the context manager protocol") from None
+ result = _enter(cm)
self._push_cm_exit(cm, _exit)
return result
@@ -600,9 +605,15 @@ class AsyncExitStack(_BaseExitStack, AbstractAsyncContextManager):
If successful, also pushes its __aexit__ method as a callback and
returns the result of the __aenter__ method.
"""
- _cm_type = type(cm)
- _exit = _cm_type.__aexit__
- result = await _cm_type.__aenter__(cm)
+ cls = type(cm)
+ try:
+ _enter = cls.__aenter__
+ _exit = cls.__aexit__
+ except AttributeError:
+ raise TypeError(f"'{cls.__module__}.{cls.__qualname__}' object does "
+ f"not support the asynchronous context manager protocol"
+ ) from None
+ result = await _enter(cm)
self._push_async_cm_exit(cm, _exit)
return result