mirror of
https://github.com/python/cpython.git
synced 2025-10-07 07:31:46 +00:00
bpo-33265: use an actual method instead of a method-like function in ExitStack (GH-6456)
`MethodType` has the exact semantics that `ExitStack` needs, so we can avoid creating a Python level closure.
This commit is contained in:
parent
ffa2c3e2c4
commit
23ab5ee667
2 changed files with 5 additions and 8 deletions
|
@ -4,6 +4,7 @@ import sys
|
||||||
import _collections_abc
|
import _collections_abc
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
from types import MethodType
|
||||||
|
|
||||||
__all__ = ["asynccontextmanager", "contextmanager", "closing", "nullcontext",
|
__all__ = ["asynccontextmanager", "contextmanager", "closing", "nullcontext",
|
||||||
"AbstractContextManager", "AbstractAsyncContextManager",
|
"AbstractContextManager", "AbstractAsyncContextManager",
|
||||||
|
@ -373,9 +374,7 @@ class _BaseExitStack:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _create_exit_wrapper(cm, cm_exit):
|
def _create_exit_wrapper(cm, cm_exit):
|
||||||
def _exit_wrapper(exc_type, exc, tb):
|
return MethodType(cm_exit, cm)
|
||||||
return cm_exit(cm, exc_type, exc, tb)
|
|
||||||
return _exit_wrapper
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _create_cb_wrapper(callback, *args, **kwds):
|
def _create_cb_wrapper(callback, *args, **kwds):
|
||||||
|
@ -443,7 +442,6 @@ class _BaseExitStack:
|
||||||
def _push_cm_exit(self, cm, cm_exit):
|
def _push_cm_exit(self, cm, cm_exit):
|
||||||
"""Helper to correctly register callbacks to __exit__ methods."""
|
"""Helper to correctly register callbacks to __exit__ methods."""
|
||||||
_exit_wrapper = self._create_exit_wrapper(cm, cm_exit)
|
_exit_wrapper = self._create_exit_wrapper(cm, cm_exit)
|
||||||
_exit_wrapper.__self__ = cm
|
|
||||||
self._push_exit_callback(_exit_wrapper, True)
|
self._push_exit_callback(_exit_wrapper, True)
|
||||||
|
|
||||||
def _push_exit_callback(self, callback, is_sync=True):
|
def _push_exit_callback(self, callback, is_sync=True):
|
||||||
|
@ -535,9 +533,7 @@ class AsyncExitStack(_BaseExitStack, AbstractAsyncContextManager):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _create_async_exit_wrapper(cm, cm_exit):
|
def _create_async_exit_wrapper(cm, cm_exit):
|
||||||
async def _exit_wrapper(exc_type, exc, tb):
|
return MethodType(cm_exit, cm)
|
||||||
return await cm_exit(cm, exc_type, exc, tb)
|
|
||||||
return _exit_wrapper
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _create_async_cb_wrapper(callback, *args, **kwds):
|
def _create_async_cb_wrapper(callback, *args, **kwds):
|
||||||
|
@ -596,7 +592,6 @@ class AsyncExitStack(_BaseExitStack, AbstractAsyncContextManager):
|
||||||
"""Helper to correctly register coroutine function to __aexit__
|
"""Helper to correctly register coroutine function to __aexit__
|
||||||
method."""
|
method."""
|
||||||
_exit_wrapper = self._create_async_exit_wrapper(cm, cm_exit)
|
_exit_wrapper = self._create_async_exit_wrapper(cm, cm_exit)
|
||||||
_exit_wrapper.__self__ = cm
|
|
||||||
self._push_exit_callback(_exit_wrapper, False)
|
self._push_exit_callback(_exit_wrapper, False)
|
||||||
|
|
||||||
async def __aenter__(self):
|
async def __aenter__(self):
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
``contextlib.ExitStack`` and ``contextlib.AsyncExitStack`` now use a method
|
||||||
|
instead of a wrapper function for exit callbacks.
|
Loading…
Add table
Add a link
Reference in a new issue