-
-
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
Initial implementation of RaisesGroup #11671
base: main
Are you sure you want to change the base?
Conversation
Hey @jakkdl thanks for this PR! I like the idea of going with
I would vote to go with just What do you think @bluetech @RonnyPfannschmidt ? |
(I think you meant python-trio/trio#2898 and not python-trio/trio#2891) |
Thanks, edited my post.
|
…as assertions with descriptive outputs for why a match failed
Some polishing of docstrings and the like left, but this should be a decent MVP. With the logic being simpler I also added an I didn't rename |
I think it is important for us to be consistent with However no need to rename the class, let us create a @bluetech this is a new feature, but given it is isolated I think we can release this in |
At this point I think it's better not to add new features to 8.0. But we can have a 8.1 not too long after. |
What about """Check if an exception matches the requirements of this RaisesGroup.
Example::
with pytest.raises(TypeError) as excinfo:
...
assert RaisesGroups(ValueError).matches(excinfo.value.__cause__)
# the above line is equivalent to
myexc = excinfo.value.__cause
assert isinstance(myexc, BaseExceptionGroup)
assert len(myexc.exceptions) == 1
assert isinstance(myexc.exceptions[0], ValueError)
""" |
Definitely, but I believe the idea is to eventually have a |
No that's a different thing, this is for checking a constructed exception that hasn't been raised - something that with pytest.raises_group(TypeError, check=lambda x: "foo" in getattr(x, "__notes__", ())):
e = ExceptionGroup("", (TypeError(),))
e.add_note("foo")
raise e and in the full implementation with with trio.RaisesGroup(trio.Matcher(TypeError, match="bar"), match="foo")):
raise ExceptionGroup("foo", (TypeError("bar"),)) but with pytest.raises(TypeError) as exc_info:
...
myexc = excinfo.value.__cause__
assert isinstance(myexc, BaseExceptionGroup)
assert len(myexc.exceptions) == 1
assert isinstance(myexc.exceptions[0], ValueError) could now be written with pytest.raises(TypeError) as exc_info:
...
assert pytest.raises_group(ValueError).matches(excinfo.value.__cause__) or if using expected_cause = pytest.raises_group(ValueError)
with pytest.raises_group(TypeError, check=lambda x: expected_cause.matches(x.__cause__)):
... Exposing that functionality was trivial, since that's already what was used internally, and cleaned up several instances in the test suite. The equivalent in non-exceptiongroup cases would be: with pytest.raises(TypeError) as exc_info:
...
assert isinstance(exc_info.value.__cause__, ValueError) But I guess if you want to continue with the super minimal public API, I can simply make |
Initially I wanted to keep the API really simple, to avoid committing to something more complex right now, because I was hoping to get this released in 8.0. But given this will no longer land in 8.0x, I think we can have more detailed discussion to include a more complete API regarding matches. Another option is to actually hold deciding on a "matches" API/solution, taking advantage that trio has already released its own API, and see how it fares on the wild. |
@bluetech @RonnyPfannschmidt @The-Compiler @Zac-HD thoughts? |
|
minor note that the parameter is named
I might play around with the "full" implementation in the trio repository to see how to add better messages on failure for nested groups and the like, to see if both
It seems reasonable to expose I do think it's possibly a bit problematic that with pytest.raises(ValueError):
... and with pytest.raises_group(ValueError):
... are so similar, esp when there's tons of parameters and other busy stuff around it, whereas |
Hi all - it's been quite a while since we started on this, and the Trio version has been working smoothly for most of that time now. I'd like to propose that we adopt that into Pytest essentially unchanged, just using snake_case for the name, and merge in time for 9.0. Any objections? @jakkdl, can you rebase + add the remaining parts + ensure we get good test coverage? |
…if it's a BaseExceptionGroup, ValueError->TypeError on wrong type
@graingert no clue why I got a random fail on |
Bizarre, the match is clearly present in the output |
Oh the output is on the stdout not the stderr, very strange. It looks like the gc was triggered even though it was disabled |
…n. export raises_group as a convenience alias.
oh it's not random https://github.com/pytest-dev/pytest/actions/runs/13035797919/job/36365825317?pr=11671 |
Oh I'm somewhat of an idiot, how's disable_gc supposed to work across into a subprocess I have this failing locally. |
Done! There's a couple decision points:
|
something like this: From 76deeca5aa5cee73e973f5c667c3f73b68892b48 Mon Sep 17 00:00:00 2001
From: Thomas Grainger <[email protected]>
Date: Wed, 29 Jan 2025 17:02:09 +0000
Subject: [PATCH] disable gc at a process level for unraisablehook tests
---
testing/test_unraisableexception.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/testing/test_unraisableexception.py b/testing/test_unraisableexception.py
index 3f191073e..df5894af5 100644
--- a/testing/test_unraisableexception.py
+++ b/testing/test_unraisableexception.py
@@ -321,6 +321,9 @@ def test_refcycle_unraisable_warning_filter_default(pytester: Pytester) -> None:
# see: https://github.com/pytest-dev/pytest/pull/13057#discussion_r1888396126
pytester.makepyfile(
test_it="""
+ import gc
+ gc.disable()
+
import pytest
class BrokenDel:
@@ -335,8 +338,7 @@ def test_refcycle_unraisable_warning_filter_default(pytester: Pytester) -> None:
"""
)
- with _disable_gc():
- result = pytester.runpytest_subprocess("-Wdefault")
+ result = pytester.runpytest_subprocess("-Wdefault")
assert result.ret == pytest.ExitCode.OK
--
2.43.0 I can only guess that something in the new pluggy with py installed causes a threshold of memory allocated to be reached which runs the GC which wasn't correctly disabled. do you want me to push to this branch? or open a new PR with just this patch? |
It might take some time before this PR gets merged, so you probably want it in a separate one :) |
@jakkdl I suggest replacing this with a fresh PR, that can describe exactly what we're doing and reference the Trio implementation - I'm concerned that reviewing this with the stale comments above will get confusing. Plausibly waiting until after the gc patch lands so that we can start from green CI. |
This is an alternative implementation to #11656, to fix #11538
Instead of doing
this condenses it to
which also means it doesn't do any modifications to
pytest.raises
orRaisesContext
TODO:
pytest.mark.xfail(raises=RaisesGroup(...))
ExceptionGroup
ergonomics inpytest.param(..., marks=xfail(raises=...))
#12504