File tree 2 files changed +53
-1
lines changed
2 files changed +53
-1
lines changed Original file line number Diff line number Diff line change @@ -107,3 +107,37 @@ def some_other_context_manager():
107
107
108
108
def is_contextmanager (func ):
109
109
return getattr (func , "__code__" , None ) in _ctxm_code_samples
110
+
111
+
112
+ @contextmanager
113
+ def breakable_section ():
114
+ """
115
+ Useful for getting out of some deep nesting, as an alternative to a closure:
116
+
117
+ item = None
118
+ with breakable_section() as Break:
119
+ if alpha:
120
+ item = alpha.value
121
+ raise Break
122
+
123
+ if beta:
124
+ for opt in beta.items:
125
+ if opt.is_the_one:
126
+ item = opt.value
127
+ raise Break
128
+
129
+ Note that each 'Break' class this context-manager yield is unique,
130
+ i.e it will only be caught by the context-manager that created it:
131
+
132
+ with breakable_section() as Break1:
133
+
134
+ with breakable_section() as Break2:
135
+ raise Break1
136
+
137
+ assert False # will not reach here
138
+ """
139
+ Break = type ("Break" , (Exception ,), {})
140
+ try :
141
+ yield Break
142
+ except Break :
143
+ pass
Original file line number Diff line number Diff line change 1
1
import pytest
2
- from easypy .contexts import contextmanager
2
+ from easypy .contexts import contextmanager , breakable_section
3
3
4
4
5
5
X = []
@@ -47,3 +47,21 @@ def foo():
47
47
assert X == [1 ]
48
48
49
49
assert not X
50
+
51
+
52
+ def test_breakable_section ():
53
+
54
+ a = []
55
+ with breakable_section () as Break1 :
56
+ with breakable_section () as Break2 :
57
+ with breakable_section () as Break3 :
58
+ raise Break2 ()
59
+ a += [1 ] # this will be skipped
60
+ a += [2 ] # this will be skipped
61
+ a += [3 ] # landing here
62
+ a += [4 ]
63
+
64
+ assert Break1 is not Break2
65
+ assert Break2 is not Break3
66
+ assert Break3 is not Break1
67
+ assert a == [3 , 4 ]
You can’t perform that action at this time.
0 commit comments