@@ -173,6 +173,15 @@ def whoo():
173
173
# The "gen" attribute is an implementation detail.
174
174
self .assertFalse (ctx .gen .gi_suspended )
175
175
176
+ def test_contextmanager_trap_no_yield (self ):
177
+ @contextmanager
178
+ def whoo ():
179
+ if False :
180
+ yield
181
+ ctx = whoo ()
182
+ with self .assertRaises (RuntimeError ):
183
+ ctx .__enter__ ()
184
+
176
185
def test_contextmanager_trap_second_yield (self ):
177
186
@contextmanager
178
187
def whoo ():
@@ -186,6 +195,19 @@ def whoo():
186
195
# The "gen" attribute is an implementation detail.
187
196
self .assertFalse (ctx .gen .gi_suspended )
188
197
198
+ def test_contextmanager_non_normalised (self ):
199
+ @contextmanager
200
+ def whoo ():
201
+ try :
202
+ yield
203
+ except RuntimeError :
204
+ raise SyntaxError
205
+
206
+ ctx = whoo ()
207
+ ctx .__enter__ ()
208
+ with self .assertRaises (SyntaxError ):
209
+ ctx .__exit__ (RuntimeError , None , None )
210
+
189
211
def test_contextmanager_except (self ):
190
212
state = []
191
213
@contextmanager
@@ -265,6 +287,25 @@ def test_issue29692():
265
287
self .assertEqual (ex .args [0 ], 'issue29692:Unchained' )
266
288
self .assertIsNone (ex .__cause__ )
267
289
290
+ def test_contextmanager_wrap_runtimeerror (self ):
291
+ @contextmanager
292
+ def woohoo ():
293
+ try :
294
+ yield
295
+ except Exception as exc :
296
+ raise RuntimeError (f'caught { exc } ' ) from exc
297
+
298
+ with self .assertRaises (RuntimeError ):
299
+ with woohoo ():
300
+ 1 / 0
301
+
302
+ # If the context manager wrapped StopIteration in a RuntimeError,
303
+ # we also unwrap it, because we can't tell whether the wrapping was
304
+ # done by the generator machinery or by the generator itself.
305
+ with self .assertRaises (StopIteration ):
306
+ with woohoo ():
307
+ raise StopIteration
308
+
268
309
def _create_contextmanager_attribs (self ):
269
310
def attribs (** kw ):
270
311
def decorate (func ):
@@ -276,6 +317,7 @@ def decorate(func):
276
317
@attribs (foo = 'bar' )
277
318
def baz (spam ):
278
319
"""Whee!"""
320
+ yield
279
321
return baz
280
322
281
323
def test_contextmanager_attribs (self ):
@@ -332,8 +374,11 @@ def woohoo(a, *, b):
332
374
333
375
def test_recursive (self ):
334
376
depth = 0
377
+ ncols = 0
335
378
@contextmanager
336
379
def woohoo ():
380
+ nonlocal ncols
381
+ ncols += 1
337
382
nonlocal depth
338
383
before = depth
339
384
depth += 1
@@ -347,6 +392,7 @@ def recursive():
347
392
recursive ()
348
393
349
394
recursive ()
395
+ self .assertEqual (ncols , 10 )
350
396
self .assertEqual (depth , 0 )
351
397
352
398
0 commit comments