-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
threadexception enhancements #13016
threadexception enhancements #13016
Conversation
# threads. However there might be threads that depend on some shutdown | ||
# signal that happens after pytest finishes, so we want to limit the | ||
# join time somewhat. A one second timeout seems reasonable. | ||
timeout = 1 |
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.
this is the bit of the PR I'm most unsure about. I think maybe we want to raise a deprecation warning for straggling threads - and make it into a error in pytest 9?
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.
Yeah, that seems reasonable to me.
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.
I think it is a reasonable thing for someone to run some thread unrelated to pytest, like a monitoring thread or similar (there are many which do this), and then run pytest.main()
. If I understand correctly, this would then cause an unnecessary 1s delay to the pytest run. Best case, they report a bug, worst case they just think pytest is slow and suffer through it.
So IMO, unless we can somehow restrict join_threads
only to threads started by tests, we shouldn't do it.
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.
removed in #13027
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.
Looks like a clear improvement to me! Merge when comments are addressed to your satisfaction 👍
# threads. However there might be threads that depend on some shutdown | ||
# signal that happens after pytest finishes, so we want to limit the | ||
# join time somewhat. A one second timeout seems reasonable. | ||
timeout = 1 |
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.
Yeah, that seems reasonable to me.
|
||
append( | ||
ThreadExceptionMeta( | ||
# Compute these strings here as they might change later |
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.
stale/misplaced comment?
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.
I think this is valid, I meant compute the strings in the hook rather than later on in the collect-from-deque phase
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.
I've moved the comment to the correct place. And I've gone through and checked the comments match the unraisablehook (or diverge where changes are needed)
Note the first commit in this PR was generated by claude - given the unraisablehook patch and the existing threadexception.py. It did well on the code but not so well on the comments!
# TODO: should be a test failure or error | ||
assert result.ret == pytest.ExitCode.INTERNAL_ERROR |
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.
Should we wait for this? Or open an issue to track it?
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.
I think open an issue to track this, the unraisablehook code has the same issue
Hmm the coverage is looking low, I'll look into it |
if len(errors) == 1: | ||
raise errors[0] | ||
if errors: | ||
raise ExceptionGroup("multiple thread exception warnings", errors) |
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.
this is absolutely definitely covered by tests:
pytest/testing/test_threadexception.py
Lines 136 to 162 in 7a56153
@pytest.mark.filterwarnings("error::pytest.PytestUnhandledThreadExceptionWarning") | |
def test_threadexception_warning_multiple_errors(pytester: Pytester) -> None: | |
pytester.makepyfile( | |
test_it=""" | |
import threading | |
def test_it(): | |
def oops(): | |
raise ValueError("Oops") | |
t = threading.Thread(target=oops, name="MyThread") | |
t.start() | |
t.join() | |
t = threading.Thread(target=oops, name="MyThread2") | |
t.start() | |
t.join() | |
def test_2(): pass | |
""" | |
) | |
result = pytester.runpytest() | |
assert result.ret == pytest.ExitCode.TESTS_FAILED | |
result.assert_outcomes(passed=1, failed=1) | |
result.stdout.fnmatch_lines( | |
[" | *ExceptionGroup: multiple thread exception warnings (2 sub-exceptions)"] | |
) |
what's going on?
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.
resolved, yeah? Looks like 100% coverage wherever I look
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.
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.
Oh, in the review window codecov is being dumb. idk what exactly triggers it but the codecov app/bot/thing is fairly often behind (not just in this repo), and the CI run is the best place to go look for coverage status.
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.
CI refers to https://github.com/pytest-dev/pytest/pull/13016/checks?check_run_id=33901516563, but the "Files Changed" codecov alerts refers to https://github.com/pytest-dev/pytest/pull/13016/checks?check_run_id=33900516688 - which while on the same commit it displays an orange "refresh" button that will redirect to 33901516563. Not sure how those runs differ
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.
Hmm, I think this is due to
as seen on https://docs.codecov.com/docs/github-checks
Which I think means we (and every project) needs to disable annotations
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.
opened codecov/codecov-action#1710 requesting the default be changed, but will otherwise open PR's/edit the org-level yaml to disable them.
I've done a bit more than just resolve your comments, @Zac-HD, so I'd like a re-review - if that's ok |
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.
Reviewed further changes, confirming that I'm happy to merge 🙂
As per review comment: #13016 (comment). Closes #13028. --------- Co-authored-by: Bruno Oliveira <[email protected]>
A number of threadexception enhancements:
tracemalloc
allocation traceback (if available).StopIteration
in test failures.pytest.PytestUnhandledThreadExceptionWarning
exception if raised.name
of the thread object in the excepthook which should help with resurrection of the thread.