annotate Lib/contextlib.py @ 79063:2bdc8c8ea42e

Issue #15977: Fix memory leak in Modules/_ssl.c when the function _set_npn_protocols() is called multiple times
author Christian Heimes <christian@cheimes.de>
date Thu, 20 Sep 2012 12:42:54 +0200
parents c108bc96aec6
children 15a391919deb
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
1 """Utilities for with-statement contexts. See PEP 343."""
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
2
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
3 import sys
77095
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
4 from collections import deque
46664
031dfe455585 Merged revisions 62425-62429,62434-62436,62441,62444,62446-62448,62450-62455,62463,62465-62466,62469,62474,62476-62478,62480,62485,62492,62497-62498,62500,62507,62513-62514,62516,62521,62531,62535,62545-62546,62548-62551,62553-62559,62569,62574,62577,62593,62595,62604-62606,62608,62616,62626-62627,62636,62638,62644-62645,62647-62648,62651-62653,62656,62661,62663,62680,62686-62687,62696,62699-62703,62711 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 43756
diff changeset
5 from functools import wraps
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
6
77095
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
7 __all__ = ["contextmanager", "closing", "ContextDecorator", "ExitStack"]
62652
30e1d8d08105 Issue 9110. Adding ContextDecorator to contextlib. This enables the creation of APIs that act as decorators as well as context managers. contextlib.contextmanager changed to use ContextDecorator.
Michael Foord <fuzzyman@voidspace.org.uk>
parents: 55020
diff changeset
8
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
9
62652
30e1d8d08105 Issue 9110. Adding ContextDecorator to contextlib. This enables the creation of APIs that act as decorators as well as context managers. contextlib.contextmanager changed to use ContextDecorator.
Michael Foord <fuzzyman@voidspace.org.uk>
parents: 55020
diff changeset
10 class ContextDecorator(object):
30e1d8d08105 Issue 9110. Adding ContextDecorator to contextlib. This enables the creation of APIs that act as decorators as well as context managers. contextlib.contextmanager changed to use ContextDecorator.
Michael Foord <fuzzyman@voidspace.org.uk>
parents: 55020
diff changeset
11 "A base class or mixin that enables context managers to work as decorators."
69849
e4ba097123f6 Issue #11647: allow contextmanager objects to be used as decorators as described in the docs. Initial patch by Ysj Ray.
Nick Coghlan <ncoghlan@gmail.com>
parents: 67463
diff changeset
12
e4ba097123f6 Issue #11647: allow contextmanager objects to be used as decorators as described in the docs. Initial patch by Ysj Ray.
Nick Coghlan <ncoghlan@gmail.com>
parents: 67463
diff changeset
13 def _recreate_cm(self):
e4ba097123f6 Issue #11647: allow contextmanager objects to be used as decorators as described in the docs. Initial patch by Ysj Ray.
Nick Coghlan <ncoghlan@gmail.com>
parents: 67463
diff changeset
14 """Return a recreated instance of self.
69851
9b76edfddc54 Remove trailing whitespace
Nick Coghlan <ncoghlan@gmail.com>
parents: 69849
diff changeset
15
77095
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
16 Allows an otherwise one-shot context manager like
69849
e4ba097123f6 Issue #11647: allow contextmanager objects to be used as decorators as described in the docs. Initial patch by Ysj Ray.
Nick Coghlan <ncoghlan@gmail.com>
parents: 67463
diff changeset
17 _GeneratorContextManager to support use as
77095
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
18 a decorator via implicit recreation.
69851
9b76edfddc54 Remove trailing whitespace
Nick Coghlan <ncoghlan@gmail.com>
parents: 69849
diff changeset
19
77095
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
20 This is a private interface just for _GeneratorContextManager.
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
21 See issue #11647 for details.
69849
e4ba097123f6 Issue #11647: allow contextmanager objects to be used as decorators as described in the docs. Initial patch by Ysj Ray.
Nick Coghlan <ncoghlan@gmail.com>
parents: 67463
diff changeset
22 """
e4ba097123f6 Issue #11647: allow contextmanager objects to be used as decorators as described in the docs. Initial patch by Ysj Ray.
Nick Coghlan <ncoghlan@gmail.com>
parents: 67463
diff changeset
23 return self
e4ba097123f6 Issue #11647: allow contextmanager objects to be used as decorators as described in the docs. Initial patch by Ysj Ray.
Nick Coghlan <ncoghlan@gmail.com>
parents: 67463
diff changeset
24
62652
30e1d8d08105 Issue 9110. Adding ContextDecorator to contextlib. This enables the creation of APIs that act as decorators as well as context managers. contextlib.contextmanager changed to use ContextDecorator.
Michael Foord <fuzzyman@voidspace.org.uk>
parents: 55020
diff changeset
25 def __call__(self, func):
30e1d8d08105 Issue 9110. Adding ContextDecorator to contextlib. This enables the creation of APIs that act as decorators as well as context managers. contextlib.contextmanager changed to use ContextDecorator.
Michael Foord <fuzzyman@voidspace.org.uk>
parents: 55020
diff changeset
26 @wraps(func)
30e1d8d08105 Issue 9110. Adding ContextDecorator to contextlib. This enables the creation of APIs that act as decorators as well as context managers. contextlib.contextmanager changed to use ContextDecorator.
Michael Foord <fuzzyman@voidspace.org.uk>
parents: 55020
diff changeset
27 def inner(*args, **kwds):
69849
e4ba097123f6 Issue #11647: allow contextmanager objects to be used as decorators as described in the docs. Initial patch by Ysj Ray.
Nick Coghlan <ncoghlan@gmail.com>
parents: 67463
diff changeset
28 with self._recreate_cm():
62652
30e1d8d08105 Issue 9110. Adding ContextDecorator to contextlib. This enables the creation of APIs that act as decorators as well as context managers. contextlib.contextmanager changed to use ContextDecorator.
Michael Foord <fuzzyman@voidspace.org.uk>
parents: 55020
diff changeset
29 return func(*args, **kwds)
30e1d8d08105 Issue 9110. Adding ContextDecorator to contextlib. This enables the creation of APIs that act as decorators as well as context managers. contextlib.contextmanager changed to use ContextDecorator.
Michael Foord <fuzzyman@voidspace.org.uk>
parents: 55020
diff changeset
30 return inner
30e1d8d08105 Issue 9110. Adding ContextDecorator to contextlib. This enables the creation of APIs that act as decorators as well as context managers. contextlib.contextmanager changed to use ContextDecorator.
Michael Foord <fuzzyman@voidspace.org.uk>
parents: 55020
diff changeset
31
30e1d8d08105 Issue 9110. Adding ContextDecorator to contextlib. This enables the creation of APIs that act as decorators as well as context managers. contextlib.contextmanager changed to use ContextDecorator.
Michael Foord <fuzzyman@voidspace.org.uk>
parents: 55020
diff changeset
32
67463
c03f64c71b05 Issue #10859: Make `contextlib.GeneratorContextManager` officially
Antoine Pitrou <solipsis@pitrou.net>
parents: 62652
diff changeset
33 class _GeneratorContextManager(ContextDecorator):
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
34 """Helper for @contextmanager decorator."""
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
35
69849
e4ba097123f6 Issue #11647: allow contextmanager objects to be used as decorators as described in the docs. Initial patch by Ysj Ray.
Nick Coghlan <ncoghlan@gmail.com>
parents: 67463
diff changeset
36 def __init__(self, func, *args, **kwds):
e4ba097123f6 Issue #11647: allow contextmanager objects to be used as decorators as described in the docs. Initial patch by Ysj Ray.
Nick Coghlan <ncoghlan@gmail.com>
parents: 67463
diff changeset
37 self.gen = func(*args, **kwds)
e4ba097123f6 Issue #11647: allow contextmanager objects to be used as decorators as described in the docs. Initial patch by Ysj Ray.
Nick Coghlan <ncoghlan@gmail.com>
parents: 67463
diff changeset
38 self.func, self.args, self.kwds = func, args, kwds
e4ba097123f6 Issue #11647: allow contextmanager objects to be used as decorators as described in the docs. Initial patch by Ysj Ray.
Nick Coghlan <ncoghlan@gmail.com>
parents: 67463
diff changeset
39
e4ba097123f6 Issue #11647: allow contextmanager objects to be used as decorators as described in the docs. Initial patch by Ysj Ray.
Nick Coghlan <ncoghlan@gmail.com>
parents: 67463
diff changeset
40 def _recreate_cm(self):
e4ba097123f6 Issue #11647: allow contextmanager objects to be used as decorators as described in the docs. Initial patch by Ysj Ray.
Nick Coghlan <ncoghlan@gmail.com>
parents: 67463
diff changeset
41 # _GCM instances are one-shot context managers, so the
e4ba097123f6 Issue #11647: allow contextmanager objects to be used as decorators as described in the docs. Initial patch by Ysj Ray.
Nick Coghlan <ncoghlan@gmail.com>
parents: 67463
diff changeset
42 # CM must be recreated each time a decorated function is
e4ba097123f6 Issue #11647: allow contextmanager objects to be used as decorators as described in the docs. Initial patch by Ysj Ray.
Nick Coghlan <ncoghlan@gmail.com>
parents: 67463
diff changeset
43 # called
e4ba097123f6 Issue #11647: allow contextmanager objects to be used as decorators as described in the docs. Initial patch by Ysj Ray.
Nick Coghlan <ncoghlan@gmail.com>
parents: 67463
diff changeset
44 return self.__class__(self.func, *self.args, **self.kwds)
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
45
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
46 def __enter__(self):
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
47 try:
41501
0c5019afc55b PEP 3114: rename .next() to .__next__() and add next() builtin.
Georg Brandl <georg@python.org>
parents: 40587
diff changeset
48 return next(self.gen)
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
49 except StopIteration:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
50 raise RuntimeError("generator didn't yield")
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
51
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
52 def __exit__(self, type, value, traceback):
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
53 if type is None:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
54 try:
41501
0c5019afc55b PEP 3114: rename .next() to .__next__() and add next() builtin.
Georg Brandl <georg@python.org>
parents: 40587
diff changeset
55 next(self.gen)
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
56 except StopIteration:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
57 return
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
58 else:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
59 raise RuntimeError("generator didn't stop")
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
60 else:
43756
317ba53cd45c Merged revisions 58742-58816 via svnmerge from
Guido van Rossum <guido@python.org>
parents: 43189
diff changeset
61 if value is None:
317ba53cd45c Merged revisions 58742-58816 via svnmerge from
Guido van Rossum <guido@python.org>
parents: 43189
diff changeset
62 # Need to force instantiation so we can reliably
317ba53cd45c Merged revisions 58742-58816 via svnmerge from
Guido van Rossum <guido@python.org>
parents: 43189
diff changeset
63 # tell if we get the same exception back
317ba53cd45c Merged revisions 58742-58816 via svnmerge from
Guido van Rossum <guido@python.org>
parents: 43189
diff changeset
64 value = type()
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
65 try:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
66 self.gen.throw(type, value, traceback)
37879
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 36926
diff changeset
67 raise RuntimeError("generator didn't stop after throw()")
40587
6b18a095c2e7 SF patch 1631942 by Collin Winter:
Guido van Rossum <guido@python.org>
parents: 38453
diff changeset
68 except StopIteration as exc:
37879
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 36926
diff changeset
69 # Suppress the exception *unless* it's the same exception that
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 36926
diff changeset
70 # was passed to throw(). This prevents a StopIteration
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 36926
diff changeset
71 # raised inside the "with" statement from being suppressed
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 36926
diff changeset
72 return exc is not value
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 36926
diff changeset
73 except:
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 36926
diff changeset
74 # only re-raise if it's *not* the exception that was
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 36926
diff changeset
75 # passed to throw(), because __exit__() must not raise
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 36926
diff changeset
76 # an exception unless __exit__() itself failed. But throw()
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 36926
diff changeset
77 # has to raise the exception to signal propagation, so this
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 36926
diff changeset
78 # fixes the impedance mismatch between the throw() protocol
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 36926
diff changeset
79 # and the __exit__() protocol.
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 36926
diff changeset
80 #
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 36926
diff changeset
81 if sys.exc_info()[1] is not value:
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 36926
diff changeset
82 raise
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
83
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
84
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
85 def contextmanager(func):
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
86 """@contextmanager decorator.
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
87
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
88 Typical usage:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
89
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
90 @contextmanager
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
91 def some_generator(<arguments>):
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
92 <setup>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
93 try:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
94 yield <value>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
95 finally:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
96 <cleanup>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
97
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
98 This makes this:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
99
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
100 with some_generator(<arguments>) as <variable>:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
101 <body>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
102
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
103 equivalent to this:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
104
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
105 <setup>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
106 try:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
107 <variable> = <value>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
108 <body>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
109 finally:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
110 <cleanup>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
111
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
112 """
46664
031dfe455585 Merged revisions 62425-62429,62434-62436,62441,62444,62446-62448,62450-62455,62463,62465-62466,62469,62474,62476-62478,62480,62485,62492,62497-62498,62500,62507,62513-62514,62516,62521,62531,62535,62545-62546,62548-62551,62553-62559,62569,62574,62577,62593,62595,62604-62606,62608,62616,62626-62627,62636,62638,62644-62645,62647-62648,62651-62653,62656,62661,62663,62680,62686-62687,62696,62699-62703,62711 via svnmerge from
Christian Heimes <christian@cheimes.de>
parents: 43756
diff changeset
113 @wraps(func)
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
114 def helper(*args, **kwds):
69849
e4ba097123f6 Issue #11647: allow contextmanager objects to be used as decorators as described in the docs. Initial patch by Ysj Ray.
Nick Coghlan <ncoghlan@gmail.com>
parents: 67463
diff changeset
115 return _GeneratorContextManager(func, *args, **kwds)
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
116 return helper
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
117
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
118
38453
29ae5e0fc348 Much-needed merge (using svnmerge.py this time) of trunk changes into p3yk.
Thomas Wouters <thomas@python.org>
parents: 37879
diff changeset
119 class closing(object):
29ae5e0fc348 Much-needed merge (using svnmerge.py this time) of trunk changes into p3yk.
Thomas Wouters <thomas@python.org>
parents: 37879
diff changeset
120 """Context to automatically close something at the end of a block.
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
121
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
122 Code like this:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
123
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
124 with closing(<module>.open(<arguments>)) as f:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
125 <block>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
126
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
127 is equivalent to this:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
128
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
129 f = <module>.open(<arguments>)
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
130 try:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
131 <block>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
132 finally:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
133 f.close()
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
134
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
135 """
38453
29ae5e0fc348 Much-needed merge (using svnmerge.py this time) of trunk changes into p3yk.
Thomas Wouters <thomas@python.org>
parents: 37879
diff changeset
136 def __init__(self, thing):
29ae5e0fc348 Much-needed merge (using svnmerge.py this time) of trunk changes into p3yk.
Thomas Wouters <thomas@python.org>
parents: 37879
diff changeset
137 self.thing = thing
29ae5e0fc348 Much-needed merge (using svnmerge.py this time) of trunk changes into p3yk.
Thomas Wouters <thomas@python.org>
parents: 37879
diff changeset
138 def __enter__(self):
29ae5e0fc348 Much-needed merge (using svnmerge.py this time) of trunk changes into p3yk.
Thomas Wouters <thomas@python.org>
parents: 37879
diff changeset
139 return self.thing
29ae5e0fc348 Much-needed merge (using svnmerge.py this time) of trunk changes into p3yk.
Thomas Wouters <thomas@python.org>
parents: 37879
diff changeset
140 def __exit__(self, *exc_info):
29ae5e0fc348 Much-needed merge (using svnmerge.py this time) of trunk changes into p3yk.
Thomas Wouters <thomas@python.org>
parents: 37879
diff changeset
141 self.thing.close()
77095
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
142
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
143
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
144 # Inspired by discussions on http://bugs.python.org/issue13585
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
145 class ExitStack(object):
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
146 """Context manager for dynamic management of a stack of exit callbacks
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
147
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
148 For example:
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
149
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
150 with ExitStack() as stack:
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
151 files = [stack.enter_context(open(fname)) for fname in filenames]
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
152 # All opened files will automatically be closed at the end of
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
153 # the with statement, even if attempts to open files later
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
154 # in the list throw an exception
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
155
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
156 """
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
157 def __init__(self):
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
158 self._exit_callbacks = deque()
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
159
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
160 def pop_all(self):
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
161 """Preserve the context stack by transferring it to a new instance"""
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
162 new_stack = type(self)()
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
163 new_stack._exit_callbacks = self._exit_callbacks
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
164 self._exit_callbacks = deque()
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
165 return new_stack
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
166
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
167 def _push_cm_exit(self, cm, cm_exit):
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
168 """Helper to correctly register callbacks to __exit__ methods"""
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
169 def _exit_wrapper(*exc_details):
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
170 return cm_exit(cm, *exc_details)
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
171 _exit_wrapper.__self__ = cm
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
172 self.push(_exit_wrapper)
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
173
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
174 def push(self, exit):
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
175 """Registers a callback with the standard __exit__ method signature
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
176
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
177 Can suppress exceptions the same way __exit__ methods can.
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
178
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
179 Also accepts any object with an __exit__ method (registering a call
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
180 to the method instead of the object itself)
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
181 """
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
182 # We use an unbound method rather than a bound method to follow
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
183 # the standard lookup behaviour for special methods
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
184 _cb_type = type(exit)
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
185 try:
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
186 exit_method = _cb_type.__exit__
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
187 except AttributeError:
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
188 # Not a context manager, so assume its a callable
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
189 self._exit_callbacks.append(exit)
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
190 else:
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
191 self._push_cm_exit(exit, exit_method)
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
192 return exit # Allow use as a decorator
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
193
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
194 def callback(self, callback, *args, **kwds):
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
195 """Registers an arbitrary callback and arguments.
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
196
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
197 Cannot suppress exceptions.
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
198 """
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
199 def _exit_wrapper(exc_type, exc, tb):
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
200 callback(*args, **kwds)
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
201 # We changed the signature, so using @wraps is not appropriate, but
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
202 # setting __wrapped__ may still help with introspection
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
203 _exit_wrapper.__wrapped__ = callback
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
204 self.push(_exit_wrapper)
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
205 return callback # Allow use as a decorator
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
206
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
207 def enter_context(self, cm):
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
208 """Enters the supplied context manager
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
209
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
210 If successful, also pushes its __exit__ method as a callback and
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
211 returns the result of the __enter__ method.
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
212 """
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
213 # We look up the special methods on the type to match the with statement
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
214 _cm_type = type(cm)
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
215 _exit = _cm_type.__exit__
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
216 result = _cm_type.__enter__(cm)
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
217 self._push_cm_exit(cm, _exit)
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
218 return result
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
219
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
220 def close(self):
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
221 """Immediately unwind the context stack"""
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
222 self.__exit__(None, None, None)
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
223
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
224 def __enter__(self):
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
225 return self
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
226
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
227 def __exit__(self, *exc_details):
77282
c108bc96aec6 Close #14969: Improve the handling of exception chaining in contextlib.ExitStack
Nick Coghlan <ncoghlan@gmail.com>
parents: 77260
diff changeset
228 # We manipulate the exception state so it behaves as though
c108bc96aec6 Close #14969: Improve the handling of exception chaining in contextlib.ExitStack
Nick Coghlan <ncoghlan@gmail.com>
parents: 77260
diff changeset
229 # we were actually nesting multiple with statements
c108bc96aec6 Close #14969: Improve the handling of exception chaining in contextlib.ExitStack
Nick Coghlan <ncoghlan@gmail.com>
parents: 77260
diff changeset
230 frame_exc = sys.exc_info()[1]
c108bc96aec6 Close #14969: Improve the handling of exception chaining in contextlib.ExitStack
Nick Coghlan <ncoghlan@gmail.com>
parents: 77260
diff changeset
231 def _fix_exception_context(new_exc, old_exc):
c108bc96aec6 Close #14969: Improve the handling of exception chaining in contextlib.ExitStack
Nick Coghlan <ncoghlan@gmail.com>
parents: 77260
diff changeset
232 while 1:
c108bc96aec6 Close #14969: Improve the handling of exception chaining in contextlib.ExitStack
Nick Coghlan <ncoghlan@gmail.com>
parents: 77260
diff changeset
233 exc_context = new_exc.__context__
c108bc96aec6 Close #14969: Improve the handling of exception chaining in contextlib.ExitStack
Nick Coghlan <ncoghlan@gmail.com>
parents: 77260
diff changeset
234 if exc_context in (None, frame_exc):
c108bc96aec6 Close #14969: Improve the handling of exception chaining in contextlib.ExitStack
Nick Coghlan <ncoghlan@gmail.com>
parents: 77260
diff changeset
235 break
c108bc96aec6 Close #14969: Improve the handling of exception chaining in contextlib.ExitStack
Nick Coghlan <ncoghlan@gmail.com>
parents: 77260
diff changeset
236 new_exc = exc_context
c108bc96aec6 Close #14969: Improve the handling of exception chaining in contextlib.ExitStack
Nick Coghlan <ncoghlan@gmail.com>
parents: 77260
diff changeset
237 new_exc.__context__ = old_exc
c108bc96aec6 Close #14969: Improve the handling of exception chaining in contextlib.ExitStack
Nick Coghlan <ncoghlan@gmail.com>
parents: 77260
diff changeset
238
77260
c0c7618762e5 Close #14963: Use an iterative algorithm in contextlib.ExitStack.__exit__ (Patch by Alon Horev)
Nick Coghlan <ncoghlan@gmail.com>
parents: 77095
diff changeset
239 # Callbacks are invoked in LIFO order to match the behaviour of
c0c7618762e5 Close #14963: Use an iterative algorithm in contextlib.ExitStack.__exit__ (Patch by Alon Horev)
Nick Coghlan <ncoghlan@gmail.com>
parents: 77095
diff changeset
240 # nested context managers
c0c7618762e5 Close #14963: Use an iterative algorithm in contextlib.ExitStack.__exit__ (Patch by Alon Horev)
Nick Coghlan <ncoghlan@gmail.com>
parents: 77095
diff changeset
241 suppressed_exc = False
c0c7618762e5 Close #14963: Use an iterative algorithm in contextlib.ExitStack.__exit__ (Patch by Alon Horev)
Nick Coghlan <ncoghlan@gmail.com>
parents: 77095
diff changeset
242 while self._exit_callbacks:
c0c7618762e5 Close #14963: Use an iterative algorithm in contextlib.ExitStack.__exit__ (Patch by Alon Horev)
Nick Coghlan <ncoghlan@gmail.com>
parents: 77095
diff changeset
243 cb = self._exit_callbacks.pop()
77095
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
244 try:
77260
c0c7618762e5 Close #14963: Use an iterative algorithm in contextlib.ExitStack.__exit__ (Patch by Alon Horev)
Nick Coghlan <ncoghlan@gmail.com>
parents: 77095
diff changeset
245 if cb(*exc_details):
c0c7618762e5 Close #14963: Use an iterative algorithm in contextlib.ExitStack.__exit__ (Patch by Alon Horev)
Nick Coghlan <ncoghlan@gmail.com>
parents: 77095
diff changeset
246 suppressed_exc = True
c0c7618762e5 Close #14963: Use an iterative algorithm in contextlib.ExitStack.__exit__ (Patch by Alon Horev)
Nick Coghlan <ncoghlan@gmail.com>
parents: 77095
diff changeset
247 exc_details = (None, None, None)
77095
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
248 except:
77260
c0c7618762e5 Close #14963: Use an iterative algorithm in contextlib.ExitStack.__exit__ (Patch by Alon Horev)
Nick Coghlan <ncoghlan@gmail.com>
parents: 77095
diff changeset
249 new_exc_details = sys.exc_info()
77282
c108bc96aec6 Close #14969: Improve the handling of exception chaining in contextlib.ExitStack
Nick Coghlan <ncoghlan@gmail.com>
parents: 77260
diff changeset
250 # simulate the stack of exceptions by setting the context
c108bc96aec6 Close #14969: Improve the handling of exception chaining in contextlib.ExitStack
Nick Coghlan <ncoghlan@gmail.com>
parents: 77260
diff changeset
251 _fix_exception_context(new_exc_details[1], exc_details[1])
77260
c0c7618762e5 Close #14963: Use an iterative algorithm in contextlib.ExitStack.__exit__ (Patch by Alon Horev)
Nick Coghlan <ncoghlan@gmail.com>
parents: 77095
diff changeset
252 if not self._exit_callbacks:
77095
8ef66c73b1e1 Close #13585: add contextlib.ExitStack to replace the ill-fated contextlib.nested API
Nick Coghlan <ncoghlan@gmail.com>
parents: 71037
diff changeset
253 raise
77260
c0c7618762e5 Close #14963: Use an iterative algorithm in contextlib.ExitStack.__exit__ (Patch by Alon Horev)
Nick Coghlan <ncoghlan@gmail.com>
parents: 77095
diff changeset
254 exc_details = new_exc_details
c0c7618762e5 Close #14963: Use an iterative algorithm in contextlib.ExitStack.__exit__ (Patch by Alon Horev)
Nick Coghlan <ncoghlan@gmail.com>
parents: 77095
diff changeset
255 return suppressed_exc