Skip to content
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

remove multierror #2891

Merged
merged 25 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5ff3464
remove multierror
jakkdl Nov 27, 2023
9c23ab0
remove more unused code, fix test_cancel_scope_multierror_filtering i…
jakkdl Nov 27, 2023
4cb329f
fix remaining failing tests, instantly collapse groups in nurseries i…
jakkdl Nov 28, 2023
3822dc1
bump exceptiongroup version to one that has the apport excepthook
jakkdl Nov 28, 2023
f52ea57
remove multierror_scripts, rename _core/_multierror.py to _core/_conc…
jakkdl Nov 28, 2023
4d600bc
edit some comments, remove test_ExceptionGroupNotHashable
jakkdl Nov 28, 2023
091e962
Merge branch 'master' into multierror_removal
jakkdl Nov 28, 2023
8246daf
docs: update some references to MultiError, remove section about main…
jakkdl Nov 28, 2023
a7a5a71
add newsfragment
jakkdl Nov 28, 2023
bfca5a5
Merge remote-tracking branch 'origin/master' into multierror_removal
jakkdl Nov 28, 2023
5dd4b95
update gc comments to my current state of understanding as to what ca…
jakkdl Nov 29, 2023
47ef84a
Merge remote-tracking branch 'origin/master' into multierror_removal
jakkdl Dec 16, 2023
95252ac
Merge remote-tracking branch 'origin/master' into multierror_removal
jakkdl Dec 16, 2023
9c1400c
move 'collapsible' to __notes__, clean up some stray unused-ignores, …
jakkdl Dec 16, 2023
907a2c5
update exceptiongroup message, test for it with a match
jakkdl Dec 16, 2023
3319a01
fix expected message
jakkdl Dec 16, 2023
9941762
fix mypy (this should be checked by pre-commit...)
jakkdl Dec 16, 2023
6977353
add test for loose exceptiongroup collapsing, rename test_multierror
jakkdl Dec 18, 2023
bd72a32
fix test
jakkdl Dec 18, 2023
0439e66
Apply suggestions from code review
jakkdl Dec 19, 2023
e19f341
update comments after review from a5rocks
jakkdl Dec 19, 2023
b0eb6b4
make the note more verbose
jakkdl Dec 20, 2023
d4463eb
Merge branch 'master' into multierror_removal
jakkdl Dec 20, 2023
f433fdb
fix the test
jakkdl Dec 20, 2023
3e485dc
update comment
jakkdl Dec 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions src/trio/_core/_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ def collapse_exception_group(
if (
len(exceptions) == 1
and isinstance(excgroup, BaseExceptionGroup)
and "collapsible" in str(excgroup)
and "collapsible" in getattr(excgroup, "__notes__", ())
):
exceptions[0].__traceback__ = concat_tb(
excgroup.__traceback__, exceptions[0].__traceback__
Expand Down Expand Up @@ -1128,10 +1128,12 @@ def aborted(raise_cancel: _core.RaiseCancelT) -> Abort:
try:
if not self._strict_exception_groups and len(self._pending_excs) == 1:
return self._pending_excs[0]
return BaseExceptionGroup(
"collapsible" if not self._strict_exception_groups else "TODO",
self._pending_excs,
exception = BaseExceptionGroup(
"Exceptions from Trio nursery", self._pending_excs
)
if not self._strict_exception_groups:
exception.add_note("collapsible")
return exception
TeamSpen210 marked this conversation as resolved.
Show resolved Hide resolved
finally:
# avoid a garbage cycle
# (see test_locals_destroyed_promptly_on_cancel)
Expand Down Expand Up @@ -1777,8 +1779,7 @@ async def python_wrapper(orig_coro: Awaitable[RetT]) -> RetT:
self.instruments.call("task_spawned", task)
# Special case: normally next_send should be an Outcome, but for the
# very first send we have to send a literal unboxed None.
# TODO: remove [unused-ignore] when Outcome is typed
self.reschedule(task, None) # type: ignore[arg-type, unused-ignore]
self.reschedule(task, None) # type: ignore[arg-type]
return task

def task_exited(self, task: Task, outcome: Outcome[Any]) -> None:
Expand Down Expand Up @@ -2624,18 +2625,17 @@ def unrolled_run(
# protocol of unwrapping whatever outcome gets sent in.
# Instead, we'll arrange to throw `exc` in directly,
# which works for at least asyncio and curio.
# TODO: remove [unused-ignore] when Outcome is typed
runner.reschedule(task, exc) # type: ignore[arg-type, unused-ignore]
runner.reschedule(task, exc) # type: ignore[arg-type]
task._next_send_fn = task.coro.throw
# prevent long-lived reference
# TODO: develop test for this deletion
# There's no regression test checking the necessity of this
jakkdl marked this conversation as resolved.
Show resolved Hide resolved
del msg

if "after_task_step" in runner.instruments:
runner.instruments.call("after_task_step", task)
del GLOBAL_RUN_CONTEXT.task
# prevent long-lived references
# TODO: develop test for these deletions
# There's no regression test checking the necessity of this
del task, next_send, next_send_fn

except GeneratorExit:
Expand Down
4 changes: 2 additions & 2 deletions src/trio/_core/_tests/test_multierror.py
jakkdl marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ def test_concat_tb() -> None:
assert extract_tb(get_tb(raiser2)) == entries2


# I haven't managed to get this one to fail, despite removing the `del` from
# _concat_tb.copy_tb (on a platform where the statement is executed)
# Unclear if this can still fail, removing the `del` from _concat_tb.copy_tb does not seem
# to trigger it (on a platform where the `del` is executed)
@pytest.mark.skipif(
sys.implementation.name != "cpython", reason="Only makes sense with refcounting GC"
)
Expand Down
30 changes: 26 additions & 4 deletions src/trio/_core/_tests/test_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -1210,7 +1210,7 @@ async def test_nursery_exception_chaining_doesnt_make_context_loops() -> None:
async def crasher() -> NoReturn:
raise KeyError

with pytest.raises(ExceptionGroup) as excinfo:
with pytest.raises(ExceptionGroup) as excinfo: # noqa: PT012
async with _core.open_nursery() as nursery:
nursery.start_soon(crasher)
raise ValueError
Expand Down Expand Up @@ -2528,7 +2528,9 @@ async def main() -> NoReturn:
async with _core.open_nursery():
raise Exception("foo")

with pytest.raises(ExceptionGroup) as exc:
with pytest.raises(
ExceptionGroup, match="^Exceptions from Trio nursery \\(1 sub-exception\\)$"
) as exc:
_core.run(main, strict_exception_groups=True)

assert len(exc.value.exceptions) == 1
Expand Down Expand Up @@ -2561,6 +2563,26 @@ async def test_nursery_strict_exception_groups() -> None:
assert exc.value.exceptions[0].args == ("foo",)


async def test_nursery_loose_exception_groups() -> None:
"""Test that loose exception groups can be enabled on a per-nursery basis."""
jakkdl marked this conversation as resolved.
Show resolved Hide resolved

async def raise_error() -> NoReturn:
raise RuntimeError("test error")

with pytest.raises( # noqa: PT012 # multiple statements
ExceptionGroup, match="^Exceptions from Trio nursery \\(2 sub-exceptions\\)$"
) as exc:
async with _core.open_nursery(strict_exception_groups=False) as nursery:
nursery.start_soon(raise_error)
nursery.start_soon(raise_error)

assert exc.value.__notes__ == ["collapsible"]
assert len(exc.value.exceptions) == 2
for subexc in exc.value.exceptions:
assert type(subexc) is RuntimeError
assert subexc.args == ("test error",)


async def test_nursery_collapse_strict() -> None:
"""
Test that a single exception from a nested nursery with strict semantics doesn't get
Expand All @@ -2570,7 +2592,7 @@ async def test_nursery_collapse_strict() -> None:
async def raise_error() -> NoReturn:
raise RuntimeError("test error")

with pytest.raises(ExceptionGroup) as exc:
with pytest.raises(ExceptionGroup) as exc: # noqa: PT012
async with _core.open_nursery() as nursery:
nursery.start_soon(sleep_forever)
nursery.start_soon(raise_error)
Expand All @@ -2596,7 +2618,7 @@ async def test_nursery_collapse_loose() -> None:
async def raise_error() -> NoReturn:
raise RuntimeError("test error")

with pytest.raises(ExceptionGroup) as exc:
with pytest.raises(ExceptionGroup) as exc: # noqa: PT012
async with _core.open_nursery() as nursery:
nursery.start_soon(sleep_forever)
nursery.start_soon(raise_error)
Expand Down
Loading