]> granicus.if.org Git - python/commitdiff
Removed contextlib.nested()
authorRaymond Hettinger <python@rcn.com>
Wed, 1 Jul 2009 01:32:12 +0000 (01:32 +0000)
committerRaymond Hettinger <python@rcn.com>
Wed, 1 Jul 2009 01:32:12 +0000 (01:32 +0000)
Doc/library/contextlib.rst
Lib/contextlib.py
Lib/test/test_contextlib.py

index ca37f0f16a010cfa95fea24c2e01d171cbcd1c46..2ee9e8d9899a6c45964be48b4d466429c6522e26 100644 (file)
@@ -52,55 +52,6 @@ Functions provided:
    immediately following the :keyword:`with` statement.
 
 
-.. function:: nested(mgr1[, mgr2[, ...]])
-
-   Combine multiple context managers into a single nested context manager.
-
-   This function has been deprecated in favour of the multiple manager form
-   of the :keyword:`with` statement.
-
-   The one advantage of this function over the multiple manager form of the
-   :keyword:`with` statement is that argument unpacking allows it to be
-   used with a variable number of context managers as follows::
-
-      from contextlib import nested
-
-      with nested(*managers):
-          do_something()
-
-   Note that if the :meth:`__exit__` method of one of the nested context managers
-   indicates an exception should be suppressed, no exception information will be
-   passed to any remaining outer context managers. Similarly, if the
-   :meth:`__exit__` method of one of the nested managers raises an exception, any
-   previous exception state will be lost; the new exception will be passed to the
-   :meth:`__exit__` methods of any remaining outer context managers. In general,
-   :meth:`__exit__` methods should avoid raising exceptions, and in particular they
-   should not re-raise a passed-in exception.
-
-   This function has two major quirks that have led to it being deprecated. Firstly,
-   as the context managers are all constructed before the function is invoked, the
-   :meth:`__new__` and :meth:`__init__` methods of the inner context managers are
-   not actually covered by the scope of the outer context managers. That means, for
-   example, that using :func:`nested` to open two files is a programming error as the
-   first file will not be closed promptly if an exception is thrown when opening
-   the second file.
-
-   Secondly, if the :meth:`__enter__` method of one of the inner context managers
-   raises an exception that is caught and suppressed by the :meth:`__exit__` method
-   of one of the outer context managers, this construct will raise
-   :exc:`RuntimeError` rather than skipping the body of the :keyword:`with`
-   statement.
-
-   Developers that need to support nesting of a variable number of context managers
-   can either use the :mod:`warnings` module to suppress the DeprecationWarning
-   raised by this function or else use this function as a model for an application
-   specific implementation.
-
-   .. deprecated:: 3.1
-      The with-statement now supports this functionality directly (without the
-      confusing error prone quirks).
-
-
 .. function:: closing(thing)
 
    Return a context manager that closes *thing* upon completion of the block.  This
index bffa0c49023b822034762095ff3438f7bd1667d9..d14c07b325f837ea92f056c84b918f24c260aa39 100644 (file)
@@ -85,51 +85,6 @@ def contextmanager(func):
     return helper
 
 
-@contextmanager
-def nested(*managers):
-    """Combine multiple context managers into a single nested context manager.
-
-   This function has been deprecated in favour of the multiple manager form
-   of the with statement.
-
-   The one advantage of this function over the multiple manager form of the
-   with statement is that argument unpacking allows it to be
-   used with a variable number of context managers as follows:
-
-      with nested(*managers):
-          do_something()
-
-    """
-    warn("With-statements now directly support multiple context managers",
-        DeprecationWarning, 3)
-    exits = []
-    vars = []
-    exc = (None, None, None)
-    try:
-        for mgr in managers:
-            exit = mgr.__exit__
-            enter = mgr.__enter__
-            vars.append(enter())
-            exits.append(exit)
-        yield vars
-    except:
-        exc = sys.exc_info()
-    finally:
-        while exits:
-            exit = exits.pop()
-            try:
-                if exit(*exc):
-                    exc = (None, None, None)
-            except:
-                exc = sys.exc_info()
-        if exc != (None, None, None):
-            # Don't rely on sys.exc_info() still containing
-            # the right information. Another exception may
-            # have been raised and caught by an exit method
-            # exc[1] already has the __traceback__ attribute populated
-            raise exc[1]
-
-
 class closing(object):
     """Context to automatically close something at the end of a block.
 
index 015a0c51951b9f04efeabc721ca8d5216323bff9..bdf4776b57c0c56e7cfe1f56fb41fc7c8b28e6d4 100644 (file)
@@ -101,128 +101,6 @@ class ContextManagerTestCase(unittest.TestCase):
         self.assertEqual(baz.foo, 'bar')
         self.assertEqual(baz.__doc__, "Whee!")
 
-class NestedTestCase(unittest.TestCase):
-
-    # XXX This needs more work
-
-    def test_nested(self):
-        @contextmanager
-        def a():
-            yield 1
-        @contextmanager
-        def b():
-            yield 2
-        @contextmanager
-        def c():
-            yield 3
-        with nested(a(), b(), c()) as (x, y, z):
-            self.assertEqual(x, 1)
-            self.assertEqual(y, 2)
-            self.assertEqual(z, 3)
-
-    def test_nested_cleanup(self):
-        state = []
-        @contextmanager
-        def a():
-            state.append(1)
-            try:
-                yield 2
-            finally:
-                state.append(3)
-        @contextmanager
-        def b():
-            state.append(4)
-            try:
-                yield 5
-            finally:
-                state.append(6)
-        try:
-            with nested(a(), b()) as (x, y):
-                state.append(x)
-                state.append(y)
-                1/0
-        except ZeroDivisionError:
-            self.assertEqual(state, [1, 4, 2, 5, 6, 3])
-        else:
-            self.fail("Didn't raise ZeroDivisionError")
-
-    def test_nested_right_exception(self):
-        state = []
-        @contextmanager
-        def a():
-            yield 1
-        class b(object):
-            def __enter__(self):
-                return 2
-            def __exit__(self, *exc_info):
-                try:
-                    raise Exception()
-                except:
-                    pass
-        try:
-            with nested(a(), b()) as (x, y):
-                1/0
-        except ZeroDivisionError:
-            self.assertEqual((x, y), (1, 2))
-        except Exception:
-            self.fail("Reraised wrong exception")
-        else:
-            self.fail("Didn't raise ZeroDivisionError")
-
-    def test_nested_b_swallows(self):
-        @contextmanager
-        def a():
-            yield
-        @contextmanager
-        def b():
-            try:
-                yield
-            except:
-                # Swallow the exception
-                pass
-        try:
-            with nested(a(), b()):
-                1/0
-        except ZeroDivisionError:
-            self.fail("Didn't swallow ZeroDivisionError")
-
-    def test_nested_break(self):
-        @contextmanager
-        def a():
-            yield
-        state = 0
-        while True:
-            state += 1
-            with nested(a(), a()):
-                break
-            state += 10
-        self.assertEqual(state, 1)
-
-    def test_nested_continue(self):
-        @contextmanager
-        def a():
-            yield
-        state = 0
-        while state < 3:
-            state += 1
-            with nested(a(), a()):
-                continue
-            state += 10
-        self.assertEqual(state, 3)
-
-    def test_nested_return(self):
-        @contextmanager
-        def a():
-            try:
-                yield
-            except:
-                pass
-        def foo():
-            with nested(a(), a()):
-                return 1
-            return 10
-        self.assertEqual(foo(), 1)
-
 class ClosingTestCase(unittest.TestCase):
 
     # XXX This needs more work