-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Generate full stack traces for inlineCallbacks #814
Conversation
|
Just in case, without this hunk the one failing test suddenly passes. I hadn't too much time to investigate why it was necessary to pass None in this one particular case, as every other case does pass self.tb wherever a traceback is needed. I think I'll need to make a test case that would also check that the erroneous behavior on Python 3 is really gone. Do I make it into a new pull request? |
|
@jafd You can make a pull request against this branch https://github.com/tardyp/twisted/tree/9176-inlinetracebacks , that way, you and @tardyp can collaborate together an move this along faster. |
e5a0673
to
ce4861a
Compare
|
Not quite sure, as this branch adds a specific test for the problem described. Would be a shame to lose it. |
|
Right. This branch has one commit, which improve the traceback generation for inlineCallbacks. I'll rebase them when #813 lands |
8e2270e
to
1a1dc55
Compare
|
@tardyp I updated your branch |
|
|
||
| def test_forwardLotsOfTracebacks(self): | ||
| """ | ||
| Test that several chained inlineCallbacks gives information about all generators |
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.
Docstring here is OK, but try to reword it so that Test that is not there, since it is obvious that it is a test. Twisted prefers to follow
docstring conventions here: https://jml.io/pages/test-docstrings.html
1a1dc55
to
921664e
Compare
|
@rodrigc sorry it took me so long to do this trivial change.. |
|
@tardyp Everybody's got a life to live. You don't need to apologize. Thanks for following up! |
Codecov Report
@@ Coverage Diff @@
## trunk #814 +/- ##
==========================================
- Coverage 91.78% 91.47% -0.32%
==========================================
Files 843 840 -3
Lines 149435 148622 -813
Branches 13083 12980 -103
==========================================
- Hits 137164 135953 -1211
- Misses 10177 10535 +358
- Partials 2094 2134 +40 |
| """ | ||
| Several Chained inlineCallbacks gives information about all generators | ||
|
|
||
| Reproducing #9176 |
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.
the docstring for a test should not make a reference to any bugfix, but rather be self-contained and fully describe the performed action and the expected result.
Please use full sentences (with a full stop at the end) and with proper cases.
The full stop is of great help to hint whether the information is complete, or if the sentence was accidentally left unfinished.
| @inlineCallbacks | ||
| def erroring(): | ||
| raise Exception() | ||
| yield "forcing generator" |
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.
they way this is implemented now, leaves this line without coverage.
Can you do something like
yield "forcing generator"
raise Exception('some-error-marker')
In this way, the function should be converted into a generated and all the code is executed... and the marker text can be used in the assertion to make sure that the right error is raised, and this is not triggered by another error
|
@tardyp This looks pretty good. Please look at fixing the coverage and the following small errors Thanks for your work! |
f579e0d
to
7b60bf8
Compare
|
@adiroiban addressed comments, cleaned-up history and rebased |
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.
Changes look good. Thanks!
See inline comments. I don't understand why we need 2 tests.
If we really need 2, than the docstrings should be more specific about what are the diferences between the 2 tests.
I will create a copy of this branch inside twisted so that we can trigger all the tests.
Meanwhile please check the comments.
Thanks!
| Chained inlineCallbacks are forwarding the traceback informations | ||
| from generator to generator. | ||
|
|
||
| A first simple test with a couple of inline callbacks. |
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 don't know if this phrase add any useful info.
I think that the docstring should be
Chained inlineCallbacks are forwarding the traceback information from generator to generator and the whole chain is available as part of traceback.
| self.assertIn("in erroring", f.getTraceback()) | ||
| tb = f.getTraceback() | ||
| self.assertIn("in erroring", tb) | ||
| self.assertIn("Error Marker", tb) |
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.
shouldn't we also check that "calling" is part of traceback?
| """ | ||
| Several Chained inlineCallbacks gives information about all generators. | ||
|
|
||
| A wider test with a 4 chained inline callbacks. |
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.
what is the difference between 2 chained callbacks and 4 chained?
Do we need both tests?
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 agree we don't really need two tests, but the current code passes test_forwardTracebacks, but not test_forwardLotsOfTracebacks.
So if there is a regression, this adds the info whether this is in the basic traceback generation, and/or the "advanced" stack traversal code.
Then I like to have a simple basic test, and then more tests which catch corner cases that we may find later (hence the ref to bugs). This is a methodology that we use at Buildbot, I'm perfectly okay to follow the one of Twisted, and to remove the first test, if you insist.
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.
As you are explaining it now, we do need 2 tests:)
Please add all this information in the docstring, so that in 2 years from now, when someone will look at these tests will know why there are 2 tests without checking the whole PR and the history of those changes.
Thanks!
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.
Right. I tried to add more details in docstrings, and in failure.py's comments
826ff17
to
58e8784
Compare
src/twisted/python/failure.py
Outdated
| @@ -252,6 +262,7 @@ def __init__(self, exc_value=None, exc_type=None, exc_tb=None, | |||
| tb.tb_lineno, (), () | |||
| )) | |||
| tb = tb.tb_next | |||
| # merging current stack with stack stored in the Failure. | |||
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 don't know if this comment is really needed... same for the above comments.
I prefer to see as little comments as possible. For me, the current code is good enough.
In 6 month we might do a change to the code and forget to update the comment ... and then the comment will just confuse rather than help.
We have the docstring for tests to explain all the use cases which this code should support
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 added those comments because I did actually write the code 6 month ago, and I couldn't make sense of it at first glance, I needed a good 5 min in order to understand again why I did it like that.
Merging current stack with failure contained stack is the core idea of this trick. This is why I insist on it.
I think future change for this code needs to carefully understand it.
Please let me know which line exactly you think is superfluous.
| Test that chained inlineCallbacks are properly forwarding the traceback informations | ||
| from generator to generator | ||
| Reproducing #9175 | ||
| Chained inlineCallbacks are forwarding the traceback informations |
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 have pushed a commit for fixing the informations typo, but I see that it was lost.
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.
sorry. I fixed that.
If you think that they are needed, that is fine and you can keep them. For me is more important to have the tests and good docstring to the tests. But this is not a hard requirement, so if you like the comments I am ok with keeping them. Once tests are green I will merge them... but I think some will fail due to comment which don't start with capital letter :) Thanks! |
My reasoning was that the test docstring should explain the code external behaviour, and not the implementation details.
Indeed. I fixed those. |
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.
All good. Thanks.
It this a PR for new feature or for fixing a defect? :)
|
@adiroiban As a user of Twisted, I would have expected the tracebacks from inlineCallbacks to behave like that. This is why for me it is a very old bug. One could argue this was never supposed to work and say it is a new feature. |
|
@tardyp > As a user of Twisted, I would have expected the tracebacks from inlineCallbacks to behave like that. I feel the same.. so maybe this should be a bugfix. Release notes should contain the full name of the affected python object/class/module. I have pushed a small commit, also to re-trigger appveyor, as manual trigger failed. Now, at a second review something is strange with this PR. The changes are in twisted.python.failure.Failure but the tests are for twisted.internet.defer.inlineCallbacks In order to pinpoint the error, shouldn't this have at least one test in twisted.test.test_failure? Thanks! |
Before:
twisted.internet.test.test_inlinecb
ForwardTraceBackTests
test_forwardLotsOfTracebacks ... Traceback (most recent call last):
File "twisted/src/twisted/internet/defer.py", line 1532, in unwindGenerator
return _inlineCallbacks(None, gen, Deferred())
File "twisted/src/twisted/internet/defer.py", line 1386, in _inlineCallbacks
result = g.send(result)
File "twisted/src/twisted/internet/test/test_inlinecb.py", line 162, in calling3
yield erroring()
File "twisted/src/twisted/internet/defer.py", line 1532, in unwindGenerator
return _inlineCallbacks(None, gen, Deferred())
--- <exception caught here> ---
File "twisted/src/twisted/internet/defer.py", line 1386, in _inlineCallbacks
result = g.send(result)
File "twisted/src/twisted/internet/test/test_inlinecb.py", line 157, in erroring
raise Exception()
builtins.Exception:
After:
twisted.internet.test.test_inlinecb
ForwardTraceBackTests
test_forwardLotsOfTracebacks ... Traceback (most recent call last):
File "twisted/src/twisted/internet/defer.py", line 1532, in unwindGenerator
return _inlineCallbacks(None, gen, Deferred())
File "twisted/src/twisted/internet/defer.py", line 1386, in _inlineCallbacks
result = g.send(result)
File "twisted/src/twisted/internet/test/test_inlinecb.py", line 162, in calling3
yield erroring()
File "twisted/src/twisted/internet/defer.py", line 1532, in unwindGenerator
return _inlineCallbacks(None, gen, Deferred())
--- <exception caught here> ---
File "twisted/src/twisted/internet/test/test_inlinecb.py", line 170, in calling
yield calling2()
File "twisted/src/twisted/internet/test/test_inlinecb.py", line 166, in calling2
yield calling3()
File "twisted/src/twisted/internet/test/test_inlinecb.py", line 162, in calling3
yield erroring()
File "twisted/src/twisted/internet/defer.py", line 1386, in _inlineCallbacks
result = g.send(result)
File "twisted/src/twisted/internet/test/test_inlinecb.py", line 157, in erroring
raise Exception()
builtins.Exception:
bfd023c
to
707759f
Compare
Actually, that unit test demonstrated an issue with the fact that original failure was changed by the failure chaining code.
707759f
to
cc1ad07
Compare
Good point. Actually digging in those test demonstrated an issue with my code... see Fixing it adds a bit of inefficiency, though (one dict copy), but it is probably negligible compared to the stack trace fixing code. |
"The new Failure should be chained to that original Failure." Should it be the exact same Failure? or should it also include were the Failure was rethrown?
|
Added some more unit test fixes. I need to change a test written in 2007 at 4fa3523 The problem is I changed the API... before the rethrown exception was exactly the same as the original exception, now it contains info about the context of where it was re-thrown. This test has been specifically designed for inline callback. I don't see another use case of throwing a failure as an exception, so I think this make sense to change that API. @glyph git blame shows peaker as the original writter of this code I am not sure who that is, and if we can jump him in the discussion. |
|
Pushed up to buildbot to run the full test suite. |
|
Hi @hawkowl I fixed txchecker issue. Shall I clean the branch and rebase? |
|
Rebase or merge trunk, either one is 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.
I have reviewed this, resolved some trivial conflicts, and it looks good to me. I think that we may want to internally do some refactoring at some point - it seems to me that this really ought to be expressed with something more akin to __cause__ and __context__, rather than treating Failure itself as an exception.
Nevertheless this is clearly more correct than what we have now.
I am going to open another PR just to get a full CI run on the merged result before landing.
based on #813
fixes https://twistedmatrix.com/trac/ticket/9176
first proof of concept for your review