--- /home/ncoghlan/devel/contextlib2/../cpython/Doc/library/contextlib.rst 2024-05-20 12:53:59.936907756 +1000 +++ /home/ncoghlan/devel/contextlib2/docs/contextlib2.rst 2024-05-23 17:39:52.671083724 +1000 @@ -1,20 +1,5 @@ -:mod:`!contextlib` --- Utilities for :keyword:`!with`\ -statement contexts -========================================================================== - -.. module:: contextlib - :synopsis: Utilities for with-statement contexts. - -**Source code:** :source:`Lib/contextlib.py` - --------------- - -This module provides utilities for common tasks involving the :keyword:`with` -statement. For more information see also :ref:`typecontextmanager` and -:ref:`context-managers`. - - -Utilities ---------- +API Reference +------------- Functions and classes provided: @@ -26,8 +11,8 @@ ``self`` while :meth:`object.__exit__` is an abstract method which by default returns ``None``. See also the definition of :ref:`typecontextmanager`. - .. versionadded:: 3.6 - + .. versionadded:: 0.6.0 + Part of the standard library in Python 3.6 and later .. class:: AbstractAsyncContextManager @@ -38,8 +23,8 @@ returns ``None``. See also the definition of :ref:`async-context-managers`. - .. versionadded:: 3.7 - + .. versionadded:: 21.6.0 + Part of the standard library in Python 3.7 and later .. decorator:: contextmanager @@ -49,12 +34,12 @@ While many objects natively support use in with statements, sometimes a resource needs to be managed that isn't a context manager in its own right, - and doesn't implement a ``close()`` method for use with ``contextlib.closing`` + and doesn't implement a ``close()`` method for use with ``contextlib2.closing`` An abstract example would be the following to ensure correct resource management:: - from contextlib import contextmanager + from contextlib2 import contextmanager @contextmanager def managed_resource(*args, **kwds): @@ -95,13 +80,10 @@ created by :func:`contextmanager` to meet the requirement that context managers support multiple invocations in order to be used as decorators). - .. versionchanged:: 3.2 - Use of :class:`ContextDecorator`. - .. decorator:: asynccontextmanager - Similar to :func:`~contextlib.contextmanager`, but creates an + Similar to :func:`~contextlib2.contextmanager`, but creates an :ref:`asynchronous context manager `. This function is a :term:`decorator` that can be used to define a factory @@ -112,7 +94,7 @@ A simple example:: - from contextlib import asynccontextmanager + from contextlib2 import asynccontextmanager @asynccontextmanager async def get_connection(): @@ -126,13 +108,16 @@ async with get_connection() as conn: return conn.query('SELECT ...') - .. versionadded:: 3.7 + .. versionadded:: 21.6.0 + Part of the standard library in Python 3.7 and later, enhanced in + Python 3.10 and later to allow created async context managers to be used + as async function decorators. Context managers defined with :func:`asynccontextmanager` can be used either as decorators or with :keyword:`async with` statements:: import time - from contextlib import asynccontextmanager + from contextlib2 import asynccontextmanager @asynccontextmanager async def timeit(): @@ -151,17 +136,13 @@ created by :func:`asynccontextmanager` to meet the requirement that context managers support multiple invocations in order to be used as decorators. - .. versionchanged:: 3.10 - Async context managers created with :func:`asynccontextmanager` can - be used as decorators. - .. function:: closing(thing) Return a context manager that closes *thing* upon completion of the block. This is basically equivalent to:: - from contextlib import contextmanager + from contextlib2 import contextmanager @contextmanager def closing(thing): @@ -172,7 +153,7 @@ And lets you write code like this:: - from contextlib import closing + from contextlib2 import closing from urllib.request import urlopen with closing(urlopen('https://www.python.org')) as page: @@ -196,7 +177,7 @@ Return an async context manager that calls the ``aclose()`` method of *thing* upon completion of the block. This is basically equivalent to:: - from contextlib import asynccontextmanager + from contextlib2 import asynccontextmanager @asynccontextmanager async def aclosing(thing): @@ -209,7 +190,7 @@ generators when they happen to exit early by :keyword:`break` or an exception. For example:: - from contextlib import aclosing + from contextlib2 import aclosing async with aclosing(my_generator()) as values: async for value in values: @@ -221,7 +202,8 @@ variables work as expected, and the exit code isn't run after the lifetime of some task it depends on). - .. versionadded:: 3.10 + .. versionadded:: 21.6.0 + Part of the standard library in Python 3.10 and later .. _simplifying-support-for-single-optional-context-managers: @@ -235,10 +217,10 @@ def myfunction(arg, ignore_exceptions=False): if ignore_exceptions: # Use suppress to ignore all exceptions. - cm = contextlib.suppress(Exception) + cm = contextlib2.suppress(Exception) else: # Do not ignore any exceptions, cm has no effect. - cm = contextlib.nullcontext() + cm = contextlib2.nullcontext() with cm: # Do something @@ -269,11 +251,11 @@ async with cm as session: # Send http requests with session - .. versionadded:: 3.7 - - .. versionchanged:: 3.10 - :term:`asynchronous context manager` support was added. + .. versionadded:: 0.6.0 + Part of the standard library in Python 3.7 and later + .. versionchanged:: 21.6.0 + Updated to Python 3.10 version with :term:`asynchronous context manager` support .. function:: suppress(*exceptions) @@ -290,7 +272,7 @@ For example:: - from contextlib import suppress + from contextlib2 import suppress with suppress(FileNotFoundError): os.remove('somefile.tmp') @@ -314,13 +296,15 @@ If the code within the :keyword:`!with` block raises a :exc:`BaseExceptionGroup`, suppressed exceptions are removed from the - group. If any exceptions in the group are not suppressed, a group containing them is re-raised. + group. If any exceptions in the group are not suppressed, a group containing + them is re-raised. - .. versionadded:: 3.4 + .. versionadded:: 0.5 + Part of the standard library in Python 3.4 and later - .. versionchanged:: 3.12 - ``suppress`` now supports suppressing exceptions raised as - part of an :exc:`BaseExceptionGroup`. + .. versionchanged:: 24.6.0 + Updated to Python 3.12 version that supports suppressing exceptions raised + as part of a :exc:`BaseExceptionGroup`. .. function:: redirect_stdout(new_target) @@ -359,17 +343,19 @@ This context manager is :ref:`reentrant `. - .. versionadded:: 3.4 + .. versionadded:: 0.5 + Part of the standard library in Python 3.4 and later .. function:: redirect_stderr(new_target) - Similar to :func:`~contextlib.redirect_stdout` but redirecting + Similar to :func:`~contextlib2.redirect_stdout` but redirecting :data:`sys.stderr` to another file or file-like object. This context manager is :ref:`reentrant `. - .. versionadded:: 3.5 + .. versionadded:: 0.5 + Part of the standard library in Python 3.5 and later .. function:: chdir(path) @@ -386,7 +372,8 @@ This context manager is :ref:`reentrant `. - .. versionadded:: 3.11 + .. versionadded:: 24.6.0 + Part of the standard library in Python 3.11 and later .. class:: ContextDecorator() @@ -402,7 +389,7 @@ Example of ``ContextDecorator``:: - from contextlib import ContextDecorator + from contextlib2 import ContextDecorator class mycontext(ContextDecorator): def __enter__(self): @@ -449,7 +436,7 @@ Existing context managers that already have a base class can be extended by using ``ContextDecorator`` as a mixin class:: - from contextlib import ContextDecorator + from contextlib2 import ContextDecorator class mycontext(ContextBaseClass, ContextDecorator): def __enter__(self): @@ -464,8 +451,6 @@ statements. If this is not the case, then the original construct with the explicit :keyword:`!with` statement inside the function should be used. - .. versionadded:: 3.2 - .. class:: AsyncContextDecorator @@ -474,7 +459,7 @@ Example of ``AsyncContextDecorator``:: from asyncio import run - from contextlib import AsyncContextDecorator + from contextlib2 import AsyncContextDecorator class mycontext(AsyncContextDecorator): async def __aenter__(self): @@ -505,7 +490,8 @@ The bit in the middle Finishing - .. versionadded:: 3.10 + .. versionadded:: 21.6.0 + Part of the standard library in Python 3.10 and later .. class:: ExitStack() @@ -547,7 +533,8 @@ foundation for higher level context managers that manipulate the exit stack in application specific ways. - .. versionadded:: 3.3 + .. versionadded:: 0.4 + Part of the standard library in Python 3.3 and later .. method:: enter_context(cm) @@ -558,9 +545,10 @@ These context managers may suppress exceptions just as they normally would if used directly as part of a :keyword:`with` statement. - .. versionchanged:: 3.11 - Raises :exc:`TypeError` instead of :exc:`AttributeError` if *cm* - is not a context manager. + .. versionchanged:: 24.6.0 + When running on Python 3.11 or later, raises :exc:`TypeError` instead + of :exc:`AttributeError` if *cm* is not a context manager. This aligns + with the behaviour of :keyword:`with` statements in Python 3.11+. .. method:: push(exit) @@ -627,14 +615,16 @@ The :meth:`~ExitStack.close` method is not implemented; :meth:`aclose` must be used instead. - .. coroutinemethod:: enter_async_context(cm) + .. method:: enter_async_context(cm) + :async: Similar to :meth:`ExitStack.enter_context` but expects an asynchronous context manager. - .. versionchanged:: 3.11 - Raises :exc:`TypeError` instead of :exc:`AttributeError` if *cm* - is not an asynchronous context manager. + .. versionchanged:: 24.6.0 + When running on Python 3.11 or later, raises :exc:`TypeError` instead + of :exc:`AttributeError` if *cm* is not an asynchronous context manager. + This aligns with the behaviour of ``async with`` statements in Python 3.11+. .. method:: push_async_exit(exit) @@ -645,7 +635,8 @@ Similar to :meth:`ExitStack.callback` but expects a coroutine function. - .. coroutinemethod:: aclose() + .. method:: aclose() + :async: Similar to :meth:`ExitStack.close` but properly handles awaitables. @@ -658,13 +649,15 @@ # the async with statement, even if attempts to open a connection # later in the list raise an exception. - .. versionadded:: 3.7 + .. versionadded:: 21.6.0 + Part of the standard library in Python 3.7 and later + Examples and Recipes -------------------- This section describes some examples and recipes for making effective use of -the tools provided by :mod:`contextlib`. +the tools provided by :mod:`contextlib2`. Supporting a variable number of context managers @@ -728,7 +721,7 @@ acquisition and release functions, along with an optional validation function, and maps them to the context management protocol:: - from contextlib import contextmanager, AbstractContextManager, ExitStack + from contextlib2 import contextmanager, AbstractContextManager, ExitStack class ResourceManager(AbstractContextManager): @@ -788,7 +781,7 @@ execution at the end of a ``with`` statement, and then later decide to skip executing that callback:: - from contextlib import ExitStack + from contextlib2 import ExitStack with ExitStack() as stack: stack.callback(cleanup_resources) @@ -802,7 +795,7 @@ If a particular application uses this pattern a lot, it can be simplified even further by means of a small helper class:: - from contextlib import ExitStack + from contextlib2 import ExitStack class Callback(ExitStack): def __init__(self, callback, /, *args, **kwds): @@ -822,7 +815,7 @@ :meth:`ExitStack.callback` to declare the resource cleanup in advance:: - from contextlib import ExitStack + from contextlib2 import ExitStack with ExitStack() as stack: @stack.callback @@ -849,7 +842,7 @@ inheriting from :class:`ContextDecorator` provides both capabilities in a single definition:: - from contextlib import ContextDecorator + from contextlib2 import ContextDecorator import logging logging.basicConfig(level=logging.INFO) @@ -911,7 +904,7 @@ context managers, and will complain about the underlying generator failing to yield if an attempt is made to use them a second time:: - >>> from contextlib import contextmanager + >>> from contextlib2 import contextmanager >>> @contextmanager ... def singleuse(): ... print("Before") @@ -946,7 +939,7 @@ :func:`suppress`, :func:`redirect_stdout`, and :func:`chdir`. Here's a very simple example of reentrant use:: - >>> from contextlib import redirect_stdout + >>> from contextlib2 import redirect_stdout >>> from io import StringIO >>> stream = StringIO() >>> write_to_stream = redirect_stdout(stream) @@ -992,7 +985,7 @@ when leaving any with statement, regardless of where those callbacks were added:: - >>> from contextlib import ExitStack + >>> from contextlib2 import ExitStack >>> stack = ExitStack() >>> with stack: ... stack.callback(print, "Callback: from first context") @@ -1026,7 +1019,7 @@ Using separate :class:`ExitStack` instances instead of reusing a single instance avoids that problem:: - >>> from contextlib import ExitStack + >>> from contextlib2 import ExitStack >>> with ExitStack() as outer_stack: ... outer_stack.callback(print, "Callback: from outer context") ... with ExitStack() as inner_stack: