annotate Lib/contextlib.py @ 46567:ffeecbebf3ca

Block 2.6-only doc change.
author Georg Brandl <georg@python.org>
date Sat, 26 Apr 2008 18:28:08 +0000
parents 317ba53cd45c
children 031dfe455585
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
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
4
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
5 __all__ = ["contextmanager", "nested", "closing"]
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
6
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
7 class GeneratorContextManager(object):
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
8 """Helper for @contextmanager decorator."""
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
9
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
10 def __init__(self, gen):
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
11 self.gen = gen
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
12
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
13 def __enter__(self):
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
14 try:
41501
0c5019afc55b PEP 3114: rename .next() to .__next__() and add next() builtin.
Georg Brandl <georg@python.org>
parents: 40587
diff changeset
15 return next(self.gen)
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
16 except StopIteration:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
17 raise RuntimeError("generator didn't yield")
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
18
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
19 def __exit__(self, type, value, traceback):
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
20 if type is None:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
21 try:
41501
0c5019afc55b PEP 3114: rename .next() to .__next__() and add next() builtin.
Georg Brandl <georg@python.org>
parents: 40587
diff changeset
22 next(self.gen)
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
23 except StopIteration:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
24 return
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
25 else:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
26 raise RuntimeError("generator didn't stop")
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
27 else:
43756
317ba53cd45c Merged revisions 58742-58816 via svnmerge from
Guido van Rossum <guido@python.org>
parents: 43189
diff changeset
28 if value is None:
317ba53cd45c Merged revisions 58742-58816 via svnmerge from
Guido van Rossum <guido@python.org>
parents: 43189
diff changeset
29 # 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
30 # 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
31 value = type()
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
32 try:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
33 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
34 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
35 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
36 # 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
37 # 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
38 # 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
39 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
40 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
41 # 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
42 # 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
43 # 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
44 # 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
45 # 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
46 # 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
47 #
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 36926
diff changeset
48 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
49 raise
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
50
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 contextmanager(func):
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
53 """@contextmanager decorator.
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
54
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
55 Typical usage:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
56
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
57 @contextmanager
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
58 def some_generator(<arguments>):
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
59 <setup>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
60 try:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
61 yield <value>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
62 finally:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
63 <cleanup>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
64
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
65 This makes this:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
66
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
67 with some_generator(<arguments>) as <variable>:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
68 <body>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
69
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
70 equivalent to this:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
71
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
72 <setup>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
73 try:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
74 <variable> = <value>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
75 <body>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
76 finally:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
77 <cleanup>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
78
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
79 """
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
80 def helper(*args, **kwds):
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
81 return GeneratorContextManager(func(*args, **kwds))
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
82 try:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
83 helper.__name__ = func.__name__
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
84 helper.__doc__ = func.__doc__
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
85 helper.__dict__ = func.__dict__
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
86 except:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
87 pass
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
88 return helper
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
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
91 @contextmanager
38453
29ae5e0fc348 Much-needed merge (using svnmerge.py this time) of trunk changes into p3yk.
Thomas Wouters <thomas@python.org>
parents: 37879
diff changeset
92 def nested(*managers):
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
93 """Support multiple context managers in a single with-statement.
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
94
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
95 Code like this:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
96
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
97 with nested(A, B, C) as (X, Y, Z):
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
98 <body>
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 is equivalent to this:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
101
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
102 with A as X:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
103 with B as Y:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
104 with C as Z:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
105 <body>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
106
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
107 """
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
108 exits = []
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
109 vars = []
36926
fc10ff322df1 Um, I thought I'd already checked this in.
Guido van Rossum <guido@python.org>
parents: 36770
diff changeset
110 exc = (None, None, None)
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
111 try:
42775
d7517c306791 Merged revisions 57221-57391 via svnmerge from
Guido van Rossum <guido@python.org>
parents: 41501
diff changeset
112 for mgr in managers:
d7517c306791 Merged revisions 57221-57391 via svnmerge from
Guido van Rossum <guido@python.org>
parents: 41501
diff changeset
113 exit = mgr.__exit__
d7517c306791 Merged revisions 57221-57391 via svnmerge from
Guido van Rossum <guido@python.org>
parents: 41501
diff changeset
114 enter = mgr.__enter__
d7517c306791 Merged revisions 57221-57391 via svnmerge from
Guido van Rossum <guido@python.org>
parents: 41501
diff changeset
115 vars.append(enter())
d7517c306791 Merged revisions 57221-57391 via svnmerge from
Guido van Rossum <guido@python.org>
parents: 41501
diff changeset
116 exits.append(exit)
d7517c306791 Merged revisions 57221-57391 via svnmerge from
Guido van Rossum <guido@python.org>
parents: 41501
diff changeset
117 yield vars
d7517c306791 Merged revisions 57221-57391 via svnmerge from
Guido van Rossum <guido@python.org>
parents: 41501
diff changeset
118 except:
d7517c306791 Merged revisions 57221-57391 via svnmerge from
Guido van Rossum <guido@python.org>
parents: 41501
diff changeset
119 exc = sys.exc_info()
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
120 finally:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
121 while exits:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
122 exit = exits.pop()
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
123 try:
36926
fc10ff322df1 Um, I thought I'd already checked this in.
Guido van Rossum <guido@python.org>
parents: 36770
diff changeset
124 if exit(*exc):
fc10ff322df1 Um, I thought I'd already checked this in.
Guido van Rossum <guido@python.org>
parents: 36770
diff changeset
125 exc = (None, None, None)
36737
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
126 except:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
127 exc = sys.exc_info()
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
128 if exc != (None, None, None):
38453
29ae5e0fc348 Much-needed merge (using svnmerge.py this time) of trunk changes into p3yk.
Thomas Wouters <thomas@python.org>
parents: 37879
diff changeset
129 # Don't rely on sys.exc_info() still containing
29ae5e0fc348 Much-needed merge (using svnmerge.py this time) of trunk changes into p3yk.
Thomas Wouters <thomas@python.org>
parents: 37879
diff changeset
130 # the right information. Another exception may
29ae5e0fc348 Much-needed merge (using svnmerge.py this time) of trunk changes into p3yk.
Thomas Wouters <thomas@python.org>
parents: 37879
diff changeset
131 # have been raised and caught by an exit method
43189
d442984f290b Fix a poorly-translated raise statement in contextlib.
Collin Winter <collinw@gmail.com>
parents: 43102
diff changeset
132 # exc[1] already has the __traceback__ attribute populated
d442984f290b Fix a poorly-translated raise statement in contextlib.
Collin Winter <collinw@gmail.com>
parents: 43102
diff changeset
133 raise exc[1]
36737
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 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
137 """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
138
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
139 Code like this:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
140
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
141 with closing(<module>.open(<arguments>)) as f:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
142 <block>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
143
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
144 is equivalent to this:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
145
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
146 f = <module>.open(<arguments>)
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
147 try:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
148 <block>
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
149 finally:
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
150 f.close()
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
151
fa92fe15251a Updates to the with-statement:
Guido van Rossum <guido@python.org>
parents:
diff changeset
152 """
38453
29ae5e0fc348 Much-needed merge (using svnmerge.py this time) of trunk changes into p3yk.
Thomas Wouters <thomas@python.org>
parents: 37879
diff changeset
153 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
154 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
155 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
156 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
157 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
158 self.thing.close()