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