classification
Title: StopIteration raised in body of 'with' statement suppressed
Type: Stage:
Components: Interpreter Core Versions: Python 2.5
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: pje Nosy List: georg.brandl, graingert, pje, tcdelaney
Priority: high Keywords:

Created on 2006-04-01 00:17 by tcdelaney, last changed 2021-07-05 09:46 by graingert. This issue is now closed.

Files
File name Uploaded Description Edit
stopiteration_with.txt tcdelaney, 2006-04-01 00:20 Code and results
with_statement.diff tcdelaney, 2006-04-02 02:42 contextlib.py fix, test_with.py added tests
contextlib.diff tcdelaney, 2006-04-03 20:24 Fixed comment
Messages (8)
msg28008 - (view) Author: Tim Delaney (tcdelaney) Date: 2006-04-01 00:17
Given:

@contextmanager
def gen():
    print '__enter__'

    try:
        yield
    finally:
        print '__exit__'

with gen():
    raise StopIteration('body')


running the above results in:

__enter__
__exit__


I would have expected instead

__enter__
__exit__
Traceback (most recent call last):
  File "test25.py", line 53, in <module>
    raise StopIteration('body')
StopIteration: body


Note that doing:

with gen():
    raise GeneratorExit('body')

does the expected thing:

__enter__
__exit__
Traceback (most recent call last):
  File "test25.py", line 53, in <module>
    raise GeneratorExit('body')
GeneratorExit: body
msg28009 - (view) Author: Tim Delaney (tcdelaney) Date: 2006-04-01 00:19
Logged In: YES 
user_id=603121

Attached code and results.
msg28010 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2006-04-01 07:02
Logged In: YES 
user_id=849994

Nick, I can't tell whether this is intentional without
rereading the specs. Can you?
msg28011 - (view) Author: Tim Delaney (tcdelaney) Date: 2006-04-02 02:42
Logged In: YES 
user_id=603121

Attached diffs to test_with.py which adds tests for raising StopIteration (and GeneratorExit) from the body of a with-statement where the context manager is either a generator, or a class instance.

I think the correct behaviour is to return False from GeneratorContextManager.__exit__ if the thrown exception is a StopIteration, and the exact same instance is raised from self.gen.throw(). Diffs for this also attached.
msg28012 - (view) Author: PJ Eby (pje) * (Python committer) Date: 2006-04-03 20:06
Logged In: YES 
user_id=56214

This looks good, although the second GeneratorExit test
looks redundant.  I went ahead and checked it in, however,
on the theory that more tests are better than fewer.  :)
msg28013 - (view) Author: Tim Delaney (tcdelaney) Date: 2006-04-03 20:24
Logged In: YES 
user_id=603121

Realised I had a couple of typos in the comment added to contextlib. Fixed diff attached.
msg396978 - (view) Author: Thomas Grainger (graingert) * Date: 2021-07-05 09:42
```
import contextlib

@contextlib.contextmanager
def foo():
    yield

class StartIrritation(StopIteration):
    pass


with foo():
    raise StartIrritation
```
msg396980 - (view) Author: Thomas Grainger (graingert) * Date: 2021-07-05 09:46
apologies I meant to post this on a new ticket
History
Date User Action Args
2021-07-05 09:46:06graingertsetmessages: + msg396980
2021-07-05 09:42:53graingertsetnosy: + graingert
messages: + msg396978
2006-04-01 00:17:59tcdelaneycreate