summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/contextlib.rst49
-rw-r--r--Lib/contextlib.py45
-rw-r--r--Lib/test/test_contextlib.py122
3 files changed, 0 insertions, 216 deletions
diff --git a/Doc/library/contextlib.rst b/Doc/library/contextlib.rst
index ca37f0f..2ee9e8d 100644
--- a/Doc/library/contextlib.rst
+++ b/Doc/library/contextlib.rst
@@ -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
diff --git a/Lib/contextlib.py b/Lib/contextlib.py
index bffa0c4..d14c07b 100644
--- a/Lib/contextlib.py
+++ b/Lib/contextlib.py
@@ -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.
diff --git a/Lib/test/test_contextlib.py b/Lib/test/test_contextlib.py
index 015a0c5..bdf4776 100644
--- a/Lib/test/test_contextlib.py
+++ b/Lib/test/test_contextlib.py
@@ -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