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

Feature Suggestion: Collect multiple exceptions from hook implementations #419

Closed
MrGreenTea opened this issue Jul 11, 2023 · 10 comments
Closed

Comments

@MrGreenTea
Copy link

Currently, if one hook implementation raises an exception the rest of the implementations of that hook won't be called. This is fine in most cases, but we have some hooks for teardowns of operations and these should always be called and pytest could also have a use for this (see pytest#8217)

Our current workaround is a patch on the internal pluggy implementation to make sure all hook implementations are called and gathering all exceptions, then raising them together. This hack could form a basis for a more correct implementation and I'd be willing to work on a PR for this feature, should you accept the suggestion.

I believe it could work as a mode in the hookspec, so look something like this:

@hookspec(force_all_impls=True)  # I don't have a good name for this yet
def example_teardown():
    ...

With the addition of exception groups to python I believe this can work quite nicely.

I'm open to all feedback and think this feature needs a more in-depth discussion then I provided as of yet, but wanted to get this discussion started.

@hoefling
Copy link
Member

If the general idea is approved by pluggy maintainers, my humble suggestion on the naming is firsterror, similar to firstresult, with defaulting to True to not break existing plugins.

@RonnyPfannschmidt
Copy link
Member

Im under the impression you want signal,not Hook

@RonnyPfannschmidt
Copy link
Member

I'm going to go further and declare that's Out off scope for the Design and usage of pluggy

So from My pov it's not Worth the added complexity

@MrGreenTea
Copy link
Author

I'm going to go further and declare that's Out off scope for the Design and usage of pluggy

So from My pov it's not Worth the added complexity

Well this is unfortunate as I hoped we could have a discussion about this as it is a feature I've needed for quite some time and the workarounds we have break with most pluggy releases.

I was also personally surprised that this is not yet a feature of pluggy, as I expected the hooks to not be dependent on the correct implementation of other plugins.

Im under the impression you want signal,not Hook

What signals do you mean exactly, the signal module? How would signals solve the problem over hooks?

For some more context:

Think of the pytest_runtest_teardown hook. If any plugin' hook implementation would raise an exception other teardown implementations might not be called. pytest makes sure all fixtures are torn down by using a similar approach as I suggest here. Using atexit handlers would leave all the teardown until all tests have run through, which might be wasteful if a lot of data can't be garbace collected.

If you're not at all interested in this feature and actively against it I will close this discussion and issue, but I hope I could make my case a bit more clear.

@RonnyPfannschmidt
Copy link
Member

From the pluggy design perspective,a Hook that's raising a error is a hard failure to propagate asap

@hoefling
Copy link
Member

hoefling commented Jul 11, 2023

That's unfortunate, we hoped for smth like

pm = pluggy.PluginManager("myapp")
...
try:
    pm.hook.myhook()
except* Exception as e:
    ...  # grab all errors raised by plugins

so the first faulty plugin does not abort the multicall.

@nicoddemus
Copy link
Member

I'm not so convinced that this out of scope for pluggy TBH.

@RonnyPfannschmidt can you detail why this is a no-go/out of scope for pluggy? Detailing it would also serve as documentation why this is undersirable/out of scope for the future.

@RonnyPfannschmidt
Copy link
Member

Currently hooks are doing direct, linear extension with direct error propagations, the request is basically for the addition of a scatter/gathering ,

This in essence adds concurrency as a entirely new patterns as well as native exception groups

In turn this will also create an eventual need to provide both results and exception

As of now id consider it quite a error prone burden to add concurrency to pluggy

@RonnyPfannschmidt
Copy link
Member

closing this to be solved as part of #321

@MrGreenTea
Copy link
Author

Currently hooks are doing direct, linear extension with direct error propagations, the request is basically for the addition of a scatter/gathering ,

This in essence adds concurrency as a entirely new patterns as well as native exception groups

In turn this will also create an eventual need to provide both results and exception

As of now id consider it quite a error prone burden to add concurrency to pluggy

Another way to consider this is how first_result works. If we look at errors/exceptions as a type of return value similar to the way some type systems do (Haskell, Rust, ...) it seems to me a very straight-forward extension of the current feature set where we might call all hooks and gather their "normal" return values.

From a design perspective it would not have to be exception groups, it could just use them as they've been added for cases like this where multiple errors might occur.

I see what you mean by the eventual need for mixed results and exceptions. Right now it works without this as well. If I have three hooks, the first two return some value and the third fails with an exception, I also do not get the results but just an exception.

Thank you for listening to this and integrating it into #321. I'll keep a close look at that and thanks again for all your work on this very helpful project :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants