-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcontextlib_context_managers.py
More file actions
102 lines (77 loc) · 2.26 KB
/
contextlib_context_managers.py
File metadata and controls
102 lines (77 loc) · 2.26 KB
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
import contextlib
class Tracker:
"""Base class for noisy context managers."""
def __init__(self, i):
self.i = i
def msg(self, s):
print("{}({}): {}".format(self.__class__.__name__, self.i, s))
def __enter__(self):
self.msg("entering")
class HandleError(Tracker):
"""If an exception is received, treat it as handled."""
def __exit__(self, exc_type, exc_val, exc_tb):
received_exc = exc_val is not None
if received_exc:
self.msg("handling exception {!r}".format(exc_val))
self.msg("exiting {}".format(received_exc))
# Return boolean value indicating whether the exception was handled.
return received_exc
class PassError(Tracker):
"""If an exception is received, propagate it."""
def __exit__(self, exc_type, exc_val, exc_tb):
received_exc = exc_val is not None
if received_exc:
self.msg("passing exception {!r}".format(exc_val))
self.msg("exiting")
# Return False, indicating any exception was not handled
return False
class ErrorOnExit(Tracker):
"""Cause an exception."""
def __exit__(self, exc_type, exc_val, exc_tb):
self.msg("throw error")
raise RuntimeError("from {}".format(self.i))
class ErrorOnEnter(Tracker):
"""Cause an exception."""
def __enter__(self):
self.msg("throwing error on enter")
raise RuntimeError("from {}".format(self.i))
def __exit__(self, exc_type, exc_val, exc_tb):
self.msg("exiting")
def variable_stack(ctxs):
with contextlib.ExitStack() as stack:
for ctx in ctxs:
stack.enter_context(ctx)
print("No errors: ")
variable_stack(
[
HandleError(1),
PassError(2),
]
)
print("\nError at the end of the context stack:")
variable_stack(
[
HandleError(1),
HandleError(2),
ErrorOnExit(3),
]
)
print("\nError in the middle of the context stack: ")
variable_stack(
[
HandleError(1),
PassError(2),
ErrorOnExit(3),
HandleError(4),
]
)
try:
print("\nError ignored: ")
variable_stack(
[
PassError(1),
ErrorOnExit(2),
]
)
except RuntimeError:
print("error handled outside of context")