Index: Doc/library/contextlib.rst =================================================================== --- Doc/library/contextlib.rst (revision 85340) +++ Doc/library/contextlib.rst (working copy) @@ -85,6 +85,27 @@ ``page.close()`` will be called when the :keyword:`with` block is exited. +.. function:: nullcontext() + + Return a context manager that executes block without doing any + additional processing. + + Such a context manager can be Used as a standin if a particular + block of code is only sometimes used with a normal context + manager:: + + with optional_cm or nullcontext(): + # Perform operation, using the specified CM if one is given + + ``nullcontext`` is basically equivalent to:: + + from contextlib import contextmanager + + @contextmanager + def nullcontext(): + yield + + .. class:: ContextDecorator() A base class that enables a context manager to also be used as a decorator. Index: Lib/contextlib.py =================================================================== --- Lib/contextlib.py (revision 85340) +++ Lib/contextlib.py (working copy) @@ -4,7 +4,7 @@ from functools import wraps from warnings import warn -__all__ = ["contextmanager", "closing", "ContextDecorator"] +__all__ = ["contextmanager", "closing", "ContextDecorator", "nullcontext"] class ContextDecorator(object): @@ -119,3 +119,25 @@ return self.thing def __exit__(self, *exc_info): self.thing.close() + + +class NullContext: + """Helper for nullcontext.""" + def __enter__(self): + pass + def __exit__(self, *exc_info): + pass + +_nullcontext = NullContext() + +def nullcontext(): + """ + No-op context manager, executes block without doing any additional processing. + + Used as a standin if a particular block of code is only sometimes + used with a normal context manager: + + with optional_cm or nullcontext(): + # Perform operation, using the specified CM if one is given + """ + return _nullcontext Index: Lib/test/test_contextlib.py =================================================================== --- Lib/test/test_contextlib.py (revision 85340) +++ Lib/test/test_contextlib.py (working copy) @@ -365,6 +365,15 @@ self.assertEqual(state, [1, 'something', 999]) +class NullTestCase(unittest.TestCase): + + def test_null(self): + state = [] + with nullcontext(): + state.append(1) + self.assertEqual(state, [1]) + + # This is needed to make the test actually run under regrtest.py! def test_main(): support.run_unittest(__name__)