diff --git a/NEWS.rst b/NEWS.rst index 20a7217..017184f 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -1,6 +1,13 @@ Release History --------------- +0.6.0 (Unreleased) +^^^^^^^^^^^^^^^^^^ + +* Issue `#16 `__: + Backport `AbstractContextManager` from Python 3.6 and `nullcontext` + from Python 3.7 (patch by John Vandenberg) + 0.5.5 (2017-04-25) ^^^^^^^^^^^^^^^^^^ diff --git a/docs/index.rst b/docs/index.rst index 72c1e12..2aa13c0 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -21,11 +21,13 @@ involving the ``with`` statement. Additions Relative to the Standard Library ------------------------------------------ -This module is primarily a backport of the Python 3.5 version of -:mod:`contextlib` to earlier releases. However, it is also a proving ground -for new features not yet part of the standard library. +This module is primarily a backport of the Python 3.6 version of +:mod:`contextlib` to earlier releases. It includes `nullcontext` from +Python 3.7, however it does not yet provide async context management +support from Python 3.7. -There are currently no such features in the module. +However, it is also a proving ground for new features not yet part of the +standard library. There are currently no such features in the module. Refer to the :mod:`contextlib` documentation for details of which versions of Python 3 introduce the various APIs provided in this module. @@ -36,6 +38,19 @@ API Reference Functions and classes provided: + +.. class:: AbstractContextManager + + An :term:`abstract base class` for classes that implement + :meth:`object.__enter__` and :meth:`object.__exit__`. A default + implementation for :meth:`object.__enter__` is provided which returns + ``self`` while :meth:`object.__exit__` is an abstract method which by default + returns ``None``. + + .. versionadded:: 0.6.0 + Part of the standard library in Python 3.6 and later + + .. decorator:: contextmanager This function is a :term:`decorator` that can be used to define a factory @@ -110,6 +125,39 @@ Functions and classes provided: ``page.close()`` will be called when the :keyword:`with` block is exited. +.. function:: nullcontext(enter_result=None) + + Return a context manager that returns *enter_result* from ``__enter__``, but + otherwise does nothing. It is intended to be used as a stand-in for an + optional context manager, for example:: + + def myfunction(arg, ignore_exceptions=False): + if ignore_exceptions: + # Use suppress to ignore all exceptions. + cm = contextlib.suppress(Exception) + else: + # Do not ignore any exceptions, cm has no effect. + cm = contextlib.nullcontext() + with cm: + # Do something + + An example using *enter_result*:: + + def process_file(file_or_path): + if isinstance(file_or_path, str): + # If string, open file + cm = open(file_or_path) + else: + # Caller is responsible for closing file + cm = nullcontext(file_or_path) + + with cm as file: + # Perform processing on the file + + .. versionadded:: 0.6.0 + Part of the standard library in Python 3.7 and later + + .. function:: suppress(*exceptions) Return a context manager that suppresses any of the specified exceptions diff --git a/test_contextlib2.py b/test_contextlib2.py index a9b15d3..7c19cb8 100755 --- a/test_contextlib2.py +++ b/test_contextlib2.py @@ -963,6 +963,16 @@ class TestSuppress(unittest.TestCase): # This shouldn't raise an exception. stack.enter_context(suppress()) + +class NullcontextTestCase(unittest.TestCase): + def test_nullcontext(self): + class C: + pass + c = C() + with nullcontext(c) as c_in: + self.assertIs(c_in, c) + + if __name__ == "__main__": import unittest unittest.main()