-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Make code.FormattedExcinfo.get_source more defensive #8227
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
Conversation
When line_index was a large negative number, get_source failed on `source.lines[line_index]`. Use the same dummy Source as with a large positive line_index.
@@ -721,11 +721,11 @@ def get_source( | |||
) -> List[str]: | |||
"""Return formatted and marked up source lines.""" | |||
lines = [] | |||
if source is None or line_index >= len(source.lines): | |||
if source is not None and line_index < 0: | |||
line_index += len(source.lines) |
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 think this is insufficient still -- for example if len(source.lines)
is 4
and line_index
is -900
-- you could use %
but it would probably be a good idea to figure out why these are negative at all (or refuse to produce source when the number is negative)
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.
That's why there's line_index < 0
in the next condition :)
I'll try to investigate why this happens in the setuptools tests.
I have encountered the same error on Python 3.10, with a test using the I can induce the crash with: import ast
import pytest
def test_literal_eval():
with pytest.raises(ValueError, match="^$"):
ast.literal_eval("pytest") On Python 3.9 and below the above test fails but pytest doesn't crash. Digging into the code with PDB the traceback passed to |
We see more packages affected by this: e.g. parso It makes testing on 3.10 very hard because you cannot tell why a test failed. Can we get this merged please? What is missing? |
is it a regression in python 3.10? if so we should raise that before the beta period and probably get it fixed there instead of here |
I am not sure. Would it help if I bisected the cpython commit that changed this? |
i do wonder if there is any way to unittest this |
we should be able to use the example from the comment here, no? |
I'll try to submit a test here. |
probably, btw - @hroncok i think its possible to temporary work around this using --tb=native |
Yes, Test added here. I had a hard time naming it and describing it. Suggestions welcome. It fails without @encukou's patch and succeeds with it. |
f5844a6
to
84c2e20
Compare
84c2e20
to
0a75c8e
Compare
imho this is goo for now - i'd like @asottile to lean in and i think a upstream report is necessary (and to link it in here and the code) |
haven't had a chance to dig into the actual bug, but here's the bisection failure: python/cpython@3bd6035 python/cpython#24202
|
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.
Thanks everyone involved!
I agree we can get this in now so downstream users can use pytest
in 3.10
. We can improve the code and/or add more information later as needed.
imo if we merge it I think we should plan to revert it when upstream fixes the issue |
Sure. 👍 |
here's the bpo issue, this is definitely a regression in 3.10 and I don't think pytest should make a code change for it: https://bugs.python.org/issue43933 here's a minimal reproduction for example without pytest: class Boom:
def __enter__(self):
return self
def __exit__(self, *_):
raise AssertionError('boom!')
def main() -> int:
with Boom():
raise AssertionError('hi')
if __name__ == '__main__':
exit(main()) $ python3.10 t.py
Traceback (most recent call last):
File "/home/asottile/workspace/cpython/t.py", line 10, in main
raise AssertionError('hi')
AssertionError: hi
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/asottile/workspace/cpython/t.py", line 14, in <module>
exit(main())
File "/home/asottile/workspace/cpython/t.py", line -1, in main
File "/home/asottile/workspace/cpython/t.py", line 5, in __exit__
raise AssertionError('boom!')
AssertionError: boom! notice we get a frame with a |
imho we should, as broken pytest by python breaks other testing on that python |
it's marked as a release blocker so this will never appear in actual released versions. note also that it doesn't break all testing of python, just for a very particular subset of exceptional cases |
I agree with that sentiment. To make all points clear:
I think we should help downstream packagers here, it doesn't really cost us much. |
alright, I'll handle reverting once this is fixed 👍 |
Thank you all. |
Great, thanks! |
Make code.FormattedExcinfo.get_source more defensive (cherry picked from commit 67af623)
Make code.FormattedExcinfo.get_source more defensive (cherry picked from commit 67af623) (Michał Górny: removed type hints for 6.2.x)
this has been fixed upstream so here's the revert (I kept the test): #8729 |
Revert "Merge pull request #8227 from encukou/defensive-get_source"
I'm seeing this again with Python 3.10.0b3+ (heads/3.10:1b4addf3cb, Jun 19 2021, 01:52:02) [Clang 12.0.0 (clang-1200.0.32.29)] pytest log
|
@brechtm if you could share the code that would be helpful |
assuming this is a recent regression -- I've pinged this issue on this bpo: https://bugs.python.org/issue44297 |
Not sure whether you mean this:
|
here's the underlying traceback -- looks like
|
To be sure, I checked with Python 3.10.0b2. No issues there. |
I think you're actually hitting the cross section of one (annoying, intentional?) importlib.metadata breaking change as well as a regression in the traceback lines -- it appears importlib.metadata in 3.10b3 is unhappy with the custom |
@asottile Wow, thanks for the analysis! I guess I'll have to set a name... |
I am trying to investigate a bug in Setuptools, and I ran into this internal error in pytest:
Full traceback...
When line_index was a large negative number, get_source failed on
source.lines[line_index]
.I don't (yet) understand the underlying error (Setuptools does some creative backwards-compatibility stunts with the import machinery), but the pytest code looks like it wants to be defensive here. Possibly, using the same dummy Source as with a large positive line_index is correct.
Sorry for not including tests; I don't know how to test it properly. This is more of a bug report with attached code than a proper pull request :)
It seems related to #752 (but the pylib link there is dead).