Skip to content

bpo-24959: fix unittest.assertRaises bug where traceback entries are dropped from chained exceptions #23688

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

Merged
merged 9 commits into from
Mar 8, 2022

Conversation

iritkatriel
Copy link
Member

@iritkatriel iritkatriel commented Dec 8, 2020

Unittest applies a hack that uses the limit parameter of TracebackException to hide traceback frames from the unittest code itself. The problem with this is that the limit applies to the chained (context) exception too, so we lose frames we want to keep.

This patch replaces the hack by code that modifies the traceback to remove the frames we don't want.

https://bugs.python.org/issue24959

@iritkatriel iritkatriel changed the title bpo-25573: fix unittest.assertRaises bug where traceback entries were… bpo-42247: fix unittest.assertRaises bug where traceback entries were… Dec 8, 2020
@iritkatriel iritkatriel requested a review from voidspace December 8, 2020 10:04
@iritkatriel iritkatriel added the type-bug An unexpected behavior, bug, or error label Dec 23, 2020
@github-actions
Copy link

This PR is stale because it has been open for 30 days with no activity.

@github-actions github-actions bot added the stale Stale PR or inactive for long period of time. label Jan 23, 2021
@iritkatriel
Copy link
Member Author

iritkatriel commented Apr 9, 2021

See also issue24959

@iritkatriel iritkatriel marked this pull request as draft July 3, 2021 16:33
@serhiy-storchaka serhiy-storchaka added needs backport to 3.9 only security fixes needs backport to 3.10 only security fixes and removed stale Stale PR or inactive for long period of time. labels Sep 5, 2021
Copy link
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM in general.

I think that tracebacks in __context__ (and maybe __cause__) chains should be cleaned recursively too. For the case like:

try:
    self.assertFoo()
finally:
    self.assertBar()

@serhiy-storchaka
Copy link
Member

Is it possible to write tests which do not rely on private methods?

@iritkatriel
Copy link
Member Author

iritkatriel commented Sep 5, 2021

Thanks. I've marked this as draft because I wanted consider a different approach to this.

We recently had some changes in the traceback module that allow you to customize how frames are rendered, and also to exclude frames from the output. I think it might be better to use that approach here. I'll make another PR soon.

@iritkatriel
Copy link
Member Author

I rewrote the test to not rely on private methods.

The traceback utility we added recently doesn't help because it allows to filter FrameSummary objects (not frames) so we no longer have access to the globals.

Regarding filtering chained tracebacks - I think this is another problem. The current filtering assumes that the traceback starts in user code. With chained tracebacks I'm not sure it is (in the contrived test I tried this wasn't the case). I think we should define the use case and desired behaviour before implementing.

@iritkatriel iritkatriel marked this pull request as ready for review September 6, 2021 10:57
@iritkatriel iritkatriel changed the title bpo-42247: fix unittest.assertRaises bug where traceback entries were… bpo-42959: fix unittest.assertRaises bug where traceback entries were… Sep 6, 2021
@iritkatriel
Copy link
Member Author

Ah I've rebased against main as well.

@iritkatriel iritkatriel changed the title bpo-42959: fix unittest.assertRaises bug where traceback entries were… bpo-24959: fix unittest.assertRaises bug where traceback entries were… Sep 6, 2021
@serhiy-storchaka
Copy link
Member

The use case is:

prepare()
try:
    test()
finally:
    cleanup()

We want to acquire some resource or make some environment changes for the part of the test and release the resource or restore environment after testing, so we use the try/finally block. Now, if an assertion failed inside the block, and an error occurred in the clean up code, the new exception will override the original AssertionError which is now accessible via the __context__ link. The traceback output will contain lines from the unittest code. Note that tracebecks for __context__ should be cleaned up not only if exctype is test.failureException, but if type(value.__context__) is test.failureException, type(value.__context__.__context__) is test.failureException, etc. But it may be a different issue.

I do not know the use case for __cause__, but I would clean up them too.

Copy link
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but I'll try to write more tests. Surprisingly, there are no tests for removing unittest frames at all.

@iritkatriel
Copy link
Member Author

See testStackFrameTrimming in test_result.

@iritkatriel
Copy link
Member Author

I added the chained exceptions. I avoided recursion because it can be just a bit too deep for certain constructs involving recursion.

@yashk2810
Copy link

Hello,

Any updates on the PR? Is it possible to get this in soon? :)

Copy link
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@iritkatriel iritkatriel changed the title bpo-24959: fix unittest.assertRaises bug where traceback entries were… bpo-24959: fix unittest.assertRaises bug where traceback entries are dropped from chained exceptions Mar 8, 2022
@iritkatriel iritkatriel merged commit 88b7d86 into python:main Mar 8, 2022
@miss-islington
Copy link
Contributor

Thanks @iritkatriel for the PR 🌮🎉.. I'm working now to backport this PR to: 3.9, 3.10.
🐍🍒⛏🤖

@miss-islington
Copy link
Contributor

Sorry, @iritkatriel, I could not cleanly backport this to 3.9 due to a conflict.
Please backport using cherry_picker on command line.
cherry_picker 88b7d86a73da9388aa65c96401c2984c8c16f8db 3.9

@bedevere-bot
Copy link

GH-31775 is a backport of this pull request to the 3.10 branch.

@bedevere-bot bedevere-bot removed the needs backport to 3.10 only security fixes label Mar 8, 2022
@iritkatriel
Copy link
Member Author

Thank you @serhiy-storchaka !

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Mar 8, 2022
…dropped from chained exceptions (pythonGH-23688)

(cherry picked from commit 88b7d86)

Co-authored-by: Irit Katriel <[email protected]>
iritkatriel added a commit that referenced this pull request Mar 8, 2022
…dropped from chained exceptions (GH-23688)

(cherry picked from commit 88b7d86)
@bedevere-bot bedevere-bot removed the needs backport to 3.9 only security fixes label Mar 8, 2022
@bedevere-bot
Copy link

GH-31776 is a backport of this pull request to the 3.9 branch.

miss-islington added a commit that referenced this pull request Mar 8, 2022
…dropped from chained exceptions (GH-23688)

(cherry picked from commit 88b7d86)

Co-authored-by: Irit Katriel <[email protected]>
iritkatriel added a commit that referenced this pull request Mar 8, 2022
…dropped from chained exceptions (GH-23688) (GH-31776)

(cherry picked from commit 88b7d86)
@yashk2810
Copy link

Just to clarify: Will this work with python 3.7 or it would need to be backported?

@iritkatriel
Copy link
Member Author

It will not be backport Ed to 3.7.
https://devguide.python.org/devcycle/

hello-adam pushed a commit to hello-adam/cpython that referenced this pull request Jun 2, 2022
@iritkatriel iritkatriel deleted the bpo-42247 branch October 18, 2022 14:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants