Conversation
|
@jaraco only changelog shows up in the PR diff. Did you forget to commit something? |
…rrors using the multi-exception handling on Python 3. Fixes #1770.
f22c70d to
0cf207c
Compare
This comment has been minimized.
This comment has been minimized.
|
I started this work in maint/17.x as it was requested to be included in the 17.x line, but I realized that the benefits only apply to Python 3 anyway, so I'm proposing merging this only to master. |
| try: | ||
| hook() | ||
| except quiet_errors: | ||
| cls.run_hooks(safe) |
There was a problem hiding this comment.
It is hard to follow the control flow with this recursive iterator shrinking.
Any ideas on how to improve the readability here?
Also, I'd maybe create a partial out of this before the loop to better communicate the intent:
run_rest_of_safe_hooks = functools.partial(cls.run_hooks, safe) # Will not enter an infinite loop because it's bound to the same iterator and the loop in the previous invocation on stack consumes failed callbacks.Is there any way to avoid recursion? This looks like a case for TCO.
There was a problem hiding this comment.
I can't think of a way without recursion to (a) catch an exception and (b) within the caught exception resume processing.
I agree it's hard to read; there's a lot going on in just a few lines, and it's incorporating a lot of rarely incorporated language features.
There was a problem hiding this comment.
I can work on refining the implementation.
There was a problem hiding this comment.
The current implementation will create an exception chain whether they'll be "causes" of one another which is not exactly true and may be misleading.
Other way to do this is to chain exceptions manually setting the previous ones as exc.__reason__. The only difference would be a text message saying that the previous exception is the cause of the current one as opposed to saying that the previous exception happened while handling the current one.
Would this help?
There was a problem hiding this comment.
I'm not sure these exceptions should be chained at all. They are all somewhat independent errors... their common thread is that they're part of the same hooks on the same request. That is, I don't think they're associated as "reason for exception X is exception Y", so __reason__ doesn't sound like the right approach.
Co-Authored-By: Sviatoslav Sydorenko <wk@sydorenko.org.ua>
|
Also, I should have said that I haven't tested this other than to run the cherrypy tests. I think this behavior deserves at least a demonstration that it achieves the desired behavior, even if it's not part of a unit test. |
|
I don't understand why the tests are failing. They pass for me locally. I think there's something configured in Travis to cause warnings as errors. I'm not sure where that is. |
|
Oh, maybe it was that tests were passing on the maint/17.x branch. I hadn't tested since merging with master. |
|
Right, so I see |
|
On further consideration, I see that the error was actually in the new code, with the check for |
I created this repro, which if run on master, produces: whereas with the patch applied, the result includes both exceptions that occurred: I believe this effectively demonstrates the effectiveness of the change. Because this relies on Python 3 to achieve its ends, I'm not going to attempt to back port this to 17.x, although I welcome others to try. |
What kind of change does this PR introduce?
What is the related issue number (starting with
#)#1770
Other information:
This alternative implementation is based on the one I proposed in #1771. It uses recursion and the exception handling inherent to Python to emit multiple tracebacks. This works because
run_hooksmethod receives an iterable, so whatever is inhooksduring the recursive call are the hooks that have not yet run.Checklist:
and description in grammatically correct, complete sentences