FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
python/Lib/contextlib.py at master · pylee/python · GitHub
pylee
/
python
Public
forked from
glix/python
Notifications
You must be signed in to change notification settings
Fork
0
Star
1
Code
Pull requests
0
Actions
Projects
Wiki
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Wiki
Security and quality
Insights
Expand file tree
Breadcrumbs
python
/
Lib
/
contextlib.py
Copy path
More file actions
More file actions
Latest commit
History
History
History
153 lines (124 loc) · 4.04 KB
Breadcrumbs
python
/
Lib
/
contextlib.py
Copy path
File metadata and controls
153 lines (124 loc) · 4.04 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
"""Utilities for with-statement contexts. See PEP 343."""
import
sys
from
functools
import
wraps
__all__
=
[
"contextmanager"
,
"nested"
,
"closing"
]
class
GeneratorContextManager
(
object
):
"""Helper for @contextmanager decorator."""
def
__init__
(
self
,
gen
):
self
.
gen
=
gen
def
__enter__
(
self
):
try
:
return
self
.
gen
.
next
()
except
StopIteration
:
raise
RuntimeError
(
"generator didn't yield"
)
def
__exit__
(
self
,
type
,
value
,
traceback
):
if
type
is
None
:
try
:
self
.
gen
.
next
()
except
StopIteration
:
return
else
:
raise
RuntimeError
(
"generator didn't stop"
)
else
:
if
value
is
None
:
# Need to force instantiation so we can reliably
# tell if we get the same exception back
value
=
type
()
try
:
self
.
gen
.
throw
(
type
,
value
,
traceback
)
raise
RuntimeError
(
"generator didn't stop after throw()"
)
except
StopIteration
,
exc
:
# Suppress the exception *unless* it's the same exception that
# was passed to throw(). This prevents a StopIteration
# raised inside the "with" statement from being suppressed
return
exc
is
not
value
except
:
# only re-raise if it's *not* the exception that was
# passed to throw(), because __exit__() must not raise
# an exception unless __exit__() itself failed. But throw()
# has to raise the exception to signal propagation, so this
# fixes the impedance mismatch between the throw() protocol
# and the __exit__() protocol.
#
if
sys
.
exc_info
()[
1
]
is
not
value
:
raise
def
contextmanager
(
func
):
"""@contextmanager decorator.
Typical usage:
@contextmanager
def some_generator(<arguments>):
<setup>
try:
yield <value>
finally:
<cleanup>
This makes this:
with some_generator(<arguments>) as <variable>:
<body>
equivalent to this:
<setup>
try:
<variable> = <value>
<body>
finally:
<cleanup>
"""
@
wraps
(
func
)
def
helper
(
*
args
,
**
kwds
):
return
GeneratorContextManager
(
func
(
*
args
,
**
kwds
))
return
helper
@
contextmanager
def
nested
(
*
managers
):
"""Support multiple context managers in a single with-statement.
Code like this:
with nested(A, B, C) as (X, Y, Z):
<body>
is equivalent to this:
with A as X:
with B as Y:
with C as Z:
<body>
"""
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
raise
exc
[
0
],
exc
[
1
],
exc
[
2
]
class
closing
(
object
):
"""Context to automatically close something at the end of a block.
Code like this:
with closing(<module>.open(<arguments>)) as f:
<block>
is equivalent to this:
f = <module>.open(<arguments>)
try:
<block>
finally:
f.close()
"""
def
__init__
(
self
,
thing
):
self
.
thing
=
thing
def
__enter__
(
self
):
return
self
.
thing
def
__exit__
(
self
,
*
exc_info
):
self
.
thing
.
close
()
Back
|
FazBrowse Home
|
New Git URL