-
-
Notifications
You must be signed in to change notification settings - Fork 31.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gh-95882: fix regression in the traceback of exceptions propagated from inside a contextlib context manager #95883
Conversation
…ontextlib.asynccontextmanager
…ger-and-contextmanager
…ger-and-contextmanager
Some tests are failing. |
Oh dear, missing import. I probably need to port more tests over too I also have this as a drive by fix https://github.com/python/cpython/pull/95888/files to save a bit of |
Lib/contextlib.py
Outdated
@@ -239,6 +240,7 @@ async def __aexit__(self, typ, value, traceback): | |||
isinstance(value, (StopIteration, StopAsyncIteration)) | |||
and exc.__cause__ is value | |||
): | |||
exc.__traceback__ = traceback |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs a test for this case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@iritkatriel it doesn't look like this line does anything. If I delete it I get the same behavior, same with L176:
Lines 166 to 177 in adf2bf3
# Avoid suppressing if a StopIteration exception | |
# was passed to throw() and later wrapped into a RuntimeError | |
# (see PEP 479 for sync generators; async generators also | |
# have this behavior). But do this only if the exception wrapped | |
# by the RuntimeError is actually Stop(Async)Iteration (see | |
# issue29692). | |
if ( | |
isinstance(value, StopIteration) | |
and exc.__cause__ is value | |
): | |
exc.__traceback__ = traceback | |
return False |
Lib/test/test_contextlib.py
Outdated
self.assertEqual(frames[0].name, 'f') | ||
self.assertEqual(frames[0].line, 'yield') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@iritkatriel do you expect to see this yield
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does 3.10 do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the yield
is new, incorrect, behavior in 3.11:
import contextlib
import logging
logger = logging.getLogger("__name__")
@contextlib.contextmanager
def f():
yield
try:
with f():
raise StopIteration
except StopIteration:
logger.exception("stop iteration")
print("================ overwriting StopIteration via globals!==============")
class StopIteration(Exception):
pass
try:
with f():
raise StopIteration
except StopIteration:
logger.exception("stop iteration")
graingert@conscientious testing311 ~/projects/trio master ± python3.10 demo.py
stop iteration
Traceback (most recent call last):
File "/home/graingert/projects/trio/demo.py", line 13, in <module>
raise StopIteration
StopIteration
================ overwriting StopIteration via globals!==============
stop iteration
Traceback (most recent call last):
File "/home/graingert/projects/trio/demo.py", line 28, in <module>
raise StopIteration
StopIteration
Notice the extra yield
in the first run before overwriting StopIteration via globals
happens:
graingert@conscientious testing311 ~/projects/trio master ± python3.11 demo.py
stop iteration
Traceback (most recent call last):
File "/home/graingert/projects/trio/demo.py", line 8, in f
yield
File "/home/graingert/projects/trio/demo.py", line 13, in <module>
raise StopIteration
StopIteration
================ overwriting StopIteration via globals!==============
stop iteration
Traceback (most recent call last):
File "/home/graingert/projects/trio/demo.py", line 28, in <module>
raise StopIteration
StopIteration
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed it!
Could you make a PR against 3.10 to backport only the new tests, so we can make sure this is not changing anything? |
Misc/NEWS.d/next/Library/2022-08-11-10-02-19.gh-issue-95882.FsUr72.rst
Outdated
Show resolved
Hide resolved
Misc/NEWS.d/next/Library/2022-08-11-10-02-19.gh-issue-95882.FsUr72.rst
Outdated
Show resolved
Hide resolved
Yeah, I'll see how far I can backport it in contextlib2 too |
…ger-and-contextmanager
@iritkatriel can you re-review this please? |
Is this done? |
Once it's in a release I'll apply it to the backport |
It has to be a separate PR anyway because it will only contain the tests. Why not do it as part of the review process for this PR? |
This looks fine but I think we should see the tests pass on all 3.10 buildbots before merging this. It’s the same amount of work, we might as well do it in the right order. |
GH-100715 is a backport of this pull request to the 3.10 branch. |
…ger-and-contextmanager
Thanks @graingert for the PR, and @iritkatriel for merging it 🌮🎉.. I'm working now to backport this PR to: 3.11. |
GH-100718 is a backport of this pull request to the 3.11 branch. |
…ted from inside a contextlib context manager (pythonGH-95883) (cherry picked from commit b3722ca) Co-authored-by: Thomas Grainger <tagrain@gmail.com>
GH-100715 is a backport of this pull request to the 3.10 branch. |
…lib.asynccontextmanager