Skip to content

Commit 9ce74c5

Browse files
[3.15] gh-129605: Add more exception handling when computing suggestions in traceback.py (GH-129632) (#159983)
(cherry picked from commit 97b5f24) Co-authored-by: Adam D. Thomas <adamt@diversityarrays.com>
1 parent e9cd323 commit 9ce74c5

3 files changed

Lines changed: 54 additions & 24 deletions

File tree

‎Lib/test/test_traceback.py‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5094,6 +5094,32 @@ def func():
50945094
actual = self.get_suggestion(func)
50955095
self.assertIn("forget to import '_io'", actual)
50965096

5097+
def test_name_error_with_bad_getattr(self):
5098+
class A:
5099+
def __getattr__(self, x):
5100+
spam
5101+
5102+
actual = self.get_suggestion(A(), "eggs")
5103+
self.assertIn("name 'spam' is not defined", actual)
5104+
5105+
def test_name_error_with_bad_getattribute(self):
5106+
5107+
class A:
5108+
def __getattribute__(self, x):
5109+
spam
5110+
5111+
actual = self.get_suggestion(A(), "eggs")
5112+
self.assertIn("name 'spam' is not defined", actual)
5113+
5114+
def test_name_error_with_bad_property(self):
5115+
class A:
5116+
@property
5117+
def eggs(self):
5118+
eggs
5119+
5120+
actual = self.get_suggestion(A(), "eggs")
5121+
self.assertIn("name 'eggs' is not defined", actual)
5122+
50975123

50985124

50995125
class PurePythonSuggestionFormattingTests(

‎Lib/traceback.py‎

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1922,31 +1922,34 @@ def _compute_suggestion_error(exc_value, tb, wrong_name):
19221922
return None
19231923
else:
19241924
assert isinstance(exc_value, NameError)
1925-
# find most recent frame
1926-
if tb is None:
1925+
try:
1926+
# find most recent frame
1927+
if tb is None:
1928+
return None
1929+
while tb.tb_next is not None:
1930+
tb = tb.tb_next
1931+
frame = tb.tb_frame
1932+
d = (
1933+
list(frame.f_locals)
1934+
+ list(frame.f_globals)
1935+
+ list(frame.f_builtins)
1936+
)
1937+
d = [x for x in d if isinstance(x, str)]
1938+
if not_normalized and wrong_name in d:
1939+
return wrong_name
1940+
1941+
# Check first if we are in a method and the instance
1942+
# has the wrong name as attribute
1943+
if 'self' in frame.f_locals:
1944+
self = frame.f_locals['self']
1945+
try:
1946+
has_wrong_name = hasattr(self, wrong_name)
1947+
except Exception:
1948+
has_wrong_name = False
1949+
if has_wrong_name:
1950+
return f"self.{wrong_name}"
1951+
except Exception:
19271952
return None
1928-
while tb.tb_next is not None:
1929-
tb = tb.tb_next
1930-
frame = tb.tb_frame
1931-
d = (
1932-
list(frame.f_locals)
1933-
+ list(frame.f_globals)
1934-
+ list(frame.f_builtins)
1935-
)
1936-
d = [x for x in d if isinstance(x, str)]
1937-
if not_normalized and wrong_name in d:
1938-
return wrong_name
1939-
1940-
# Check first if we are in a method and the instance
1941-
# has the wrong name as attribute
1942-
if 'self' in frame.f_locals:
1943-
self = frame.f_locals['self']
1944-
try:
1945-
has_wrong_name = hasattr(self, wrong_name)
1946-
except Exception:
1947-
has_wrong_name = False
1948-
if has_wrong_name:
1949-
return f"self.{wrong_name}"
19501953

19511954
if not_normalized and wrong_name in d:
19521955
return wrong_name
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improve exception handling when computing suggestions in traceback.py. This fixes a bug that could cause PyREPL to exit unexpectedly.

0 commit comments

Comments
 (0)