Skip to content

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

Merged
iritkatriel merged 9 commits into
python:mainfrom
iritkatriel:bpo-42247
Mar 8, 2022
Merged

bpo-24959: fix unittest.assertRaises bug where traceback entries are dropped from chained exceptions#23688
iritkatriel merged 9 commits into
python:mainfrom
iritkatriel:bpo-42247

Conversation

@iritkatriel

@iritkatriel iritkatriel commented Dec 8, 2020

Copy link
Copy Markdown
Member

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
Copy Markdown

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

iritkatriel commented Apr 9, 2021

Copy link
Copy Markdown
Member Author

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 needs backport to 3.10 only security fixes and removed stale Stale PR or inactive for long period of time. labels Sep 5, 2021

@serhiy-storchaka serhiy-storchaka left a comment

Copy link
Copy Markdown
Member

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()

Comment thread Lib/unittest/test/test_result.py Outdated
Comment thread Lib/unittest/test/test_result.py Outdated
Comment thread Lib/unittest/test/test_result.py Outdated
@serhiy-storchaka

Copy link
Copy Markdown
Member

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

@iritkatriel

iritkatriel commented Sep 5, 2021

Copy link
Copy Markdown
Member Author

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 and others added 5 commits September 5, 2021 22:43
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
@iritkatriel

Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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.

@serhiy-storchaka serhiy-storchaka left a comment

Copy link
Copy Markdown
Member

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
Copy Markdown
Member Author

See testStackFrameTrimming in test_result.

@iritkatriel

Copy link
Copy Markdown
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
Copy Markdown

Hello,

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

@serhiy-storchaka serhiy-storchaka left a comment

Copy link
Copy Markdown
Member

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
Copy Markdown
Contributor

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

@miss-islington

Copy link
Copy Markdown
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
Copy Markdown

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
Copy Markdown
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 <1055913+iritkatriel@users.noreply.github.com>
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

Copy link
Copy Markdown

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 <1055913+iritkatriel@users.noreply.github.com>
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
Copy Markdown

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

@iritkatriel

Copy link
Copy Markdown
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