diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2021-06-29 08:28:15 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-29 08:28:15 (GMT) |
commit | 6cb145d23f5cf69b6d7414877d142747cd3d134c (patch) | |
tree | 0617efcd6911c14a1b8003bb9bee5fc68e521103 /Lib/contextlib.py | |
parent | 20a88004bae8ead66a205a125e1fe979376fc3ea (diff) | |
download | cpython-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.py | 23 |
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 |