@@ -163,6 +163,15 @@ def whoo():
163
163
# The "gen" attribute is an implementation detail.
164
164
self .assertFalse (ctx .gen .gi_suspended )
165
165
166
+ def test_contextmanager_trap_no_yield (self ):
167
+ @contextmanager
168
+ def whoo ():
169
+ if False :
170
+ yield
171
+ ctx = whoo ()
172
+ with self .assertRaises (RuntimeError ):
173
+ ctx .__enter__ ()
174
+
166
175
def test_contextmanager_trap_second_yield (self ):
167
176
@contextmanager
168
177
def whoo ():
@@ -176,6 +185,19 @@ def whoo():
176
185
# The "gen" attribute is an implementation detail.
177
186
self .assertFalse (ctx .gen .gi_suspended )
178
187
188
+ def test_contextmanager_non_normalised (self ):
189
+ @contextmanager
190
+ def whoo ():
191
+ try :
192
+ yield
193
+ except RuntimeError :
194
+ raise SyntaxError
195
+
196
+ ctx = whoo ()
197
+ ctx .__enter__ ()
198
+ with self .assertRaises (SyntaxError ):
199
+ ctx .__exit__ (RuntimeError , None , None )
200
+
179
201
def test_contextmanager_except (self ):
180
202
state = []
181
203
@contextmanager
@@ -255,6 +277,25 @@ def test_issue29692():
255
277
self .assertEqual (ex .args [0 ], 'issue29692:Unchained' )
256
278
self .assertIsNone (ex .__cause__ )
257
279
280
+ def test_contextmanager_wrap_runtimeerror (self ):
281
+ @contextmanager
282
+ def woohoo ():
283
+ try :
284
+ yield
285
+ except Exception as exc :
286
+ raise RuntimeError (f'caught { exc } ' ) from exc
287
+
288
+ with self .assertRaises (RuntimeError ):
289
+ with woohoo ():
290
+ 1 / 0
291
+
292
+ # If the context manager wrapped StopIteration in a RuntimeError,
293
+ # we also unwrap it, because we can't tell whether the wrapping was
294
+ # done by the generator machinery or by the generator itself.
295
+ with self .assertRaises (StopIteration ):
296
+ with woohoo ():
297
+ raise StopIteration
298
+
258
299
def _create_contextmanager_attribs (self ):
259
300
def attribs (** kw ):
260
301
def decorate (func ):
@@ -266,6 +307,7 @@ def decorate(func):
266
307
@attribs (foo = 'bar' )
267
308
def baz (spam ):
268
309
"""Whee!"""
310
+ yield
269
311
return baz
270
312
271
313
def test_contextmanager_attribs (self ):
@@ -322,8 +364,11 @@ def woohoo(a, *, b):
322
364
323
365
def test_recursive (self ):
324
366
depth = 0
367
+ ncols = 0
325
368
@contextmanager
326
369
def woohoo ():
370
+ nonlocal ncols
371
+ ncols += 1
327
372
nonlocal depth
328
373
before = depth
329
374
depth += 1
@@ -337,6 +382,7 @@ def recursive():
337
382
recursive ()
338
383
339
384
recursive ()
385
+ self .assertEqual (ncols , 10 )
340
386
self .assertEqual (depth , 0 )
341
387
342
388
0 commit comments