-
-
Notifications
You must be signed in to change notification settings - Fork 33.3k
gh-139531: Fix TypeError in inspect.getframeinfo when lineno is None #139535
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
gh-139531: Fix TypeError in inspect.getframeinfo when lineno is None #139535
Conversation
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.
This requires a blurb.
| if __name__ == "__main__": | ||
| unittest.main() | ||
|
|
||
| def test_getframeinfo_with_exceptiongroup(): |
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.
This test is not a test, it should be failing without the patch.
….com/PrinceNaroliya/cpython into fix/inspect-getframeinfo-lineno-None
942d6a7 to
2f7297c
Compare
2f7297c to
c1a282b
Compare
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.
This PR has many unrelated changes, duplicated ones. Please read https://devguide.python.org/getting-started/pull-request-lifecycle/. I'm converting this into a draft until it's in a better shape.
I would also suggest looking at the content of Misc/NEWS.d/next/ to see how the NEWS entries are written (we don't add references to GH issues for instance).
| @@ -28,6 +28,7 @@ | |||
| import unittest.mock | |||
| import warnings | |||
| import weakref | |||
| import unittest | |||
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.
Why reimporting this?
| @@ -6537,8 +6246,22 @@ def f(): | |||
| expected = "The source is: <<<def f():\n print(0)\n return 1 + 2\n>>>" | |||
| self.assertIn(expected, output) | |||
|
|
|||
|
|
|||
|
|
|||
| class TestInspect(unittest.TestCase): | |||
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.
Why a new class?
| with self.assertRaises(TypeError): # expect the bug to raise TypeError | ||
| try: | ||
| exec(code) | ||
| except: | ||
| tb = sys.exc_info()[2] | ||
| while tb: | ||
| info = inspect.getframeinfo(tb.tb_frame) | ||
| tb = tb.tb_next |
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 this test? we should fix the issue, not show that there is one.
| if lineno is None: | ||
| lineno = 1 |
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.
Why this change? it might happen that lineno is None and should remains so.
| ../../Lib/_colorize.py |
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 are all these changes?
|
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
|
The fix is incorrect. We need to be able to handle frames coming from reraising an exception group, while here we cannot. So it's either an interpreter issue or an inspect issue. I'm going to close this one for now. |
Issue Description:
In Python 3.12+ (tested on 3.12, 3.13, 3.14), inspect.getframeinfo() can raise a TypeError when handling exception groups:
import inspect, sys
code = """
try:
1/0
except* Exception:
raise
"""
try:
exec(code)
except:
tb = sys.exc_info()[2]
while tb:
info = inspect.getframeinfo(tb.tb_frame) # <-- TypeError occurs here
tb = tb.tb_next
Observed behavior:
For certain frames in exception groups, frame.f_lineno is None.
Existing code calculates start = lineno - 1 - context//2, which raises:
TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'
Fix Implemented
lineno = positions[0]
if lineno is None:
lineno = 1 # fallback to safe line number
Ensures that start = lineno - 1 - context//2 never raises TypeError.
Keeps behavior consistent with Python’s 1-based line numbering.
import inspect
import sys
def test_getframeinfo_with_exceptiongroup():
"""Test that inspect.getframeinfo does not raise TypeError
when handling exception groups where lineno can be None.
"""
code = """
try:
1/0
except* Exception:
raise
"""
try:
exec(code)
except:
tb = sys.exc_info()[2]
while tb:
lineno = getattr(tb.tb_frame, "f_lineno", 1)
info = inspect.getframeinfo(tb.tb_frame)
print(f"Line number: {lineno}")
tb = tb.tb_next
This test reproduces the original bug and verifies the fix.
Output example after fix:
Line number: 24
Line number: 1
✅ Results
TypeError no longer occurs for exception groups.
Backward-compatible with frames having valid lineno.
Test case ensures future regressions are prevented.
📝 Additional Notes
Safe fallback lineno = 1 follows Python’s 1-based line numbering convention.
Minimal change ensures no performance impact for normal frames.
inspect.getframeinfo()doesn't handle legitimate frames withlineno=None#139531