Skip to content

Commit 7a598d6

Browse files
committed
Simplify and add more tests
1 parent 3164cda commit 7a598d6

2 files changed

Lines changed: 50 additions & 14 deletions

File tree

Lib/test/test_traceback.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4394,6 +4394,51 @@ def __init__(self):
43944394
# Verify it's a single suggestion, not multiple
43954395
self.assertEqual(actual.count("Did you mean"), 1)
43964396

4397+
def test_getattr_nested_handles_attribute_access_exceptions(self):
4398+
# Test that exceptions raised when accessing attributes don't crash the suggestion system
4399+
class ExplodingProperty:
4400+
@property
4401+
def exploding_attr(self):
4402+
raise RuntimeError("BOOM! This property always explodes")
4403+
4404+
def __repr__(self):
4405+
raise RuntimeError("repr also explodes")
4406+
4407+
class SafeInner:
4408+
def __init__(self):
4409+
self.target = 42
4410+
4411+
class Outer:
4412+
def __init__(self):
4413+
self.exploder = ExplodingProperty() # Accessing attributes will raise
4414+
self.safe_inner = SafeInner()
4415+
4416+
# Should still suggest 'safe_inner.target' without crashing
4417+
# even though accessing exploder.target would raise an exception
4418+
actual = self.get_suggestion(Outer(), 'target')
4419+
self.assertIn("'safe_inner.target'", actual)
4420+
4421+
def test_getattr_nested_handles_hasattr_exceptions(self):
4422+
# Test that exceptions in hasattr don't crash the system
4423+
class WeirdObject:
4424+
def __getattr__(self, name):
4425+
if name == 'target':
4426+
raise RuntimeError("Can't check for target attribute")
4427+
raise AttributeError(f"No attribute {name}")
4428+
4429+
class NormalInner:
4430+
def __init__(self):
4431+
self.target = 100
4432+
4433+
class Outer:
4434+
def __init__(self):
4435+
self.weird = WeirdObject() # hasattr will raise for 'target'
4436+
self.normal = NormalInner()
4437+
4438+
# Should still find 'normal.target' even though weird.target check fails
4439+
actual = self.get_suggestion(Outer(), 'target')
4440+
self.assertIn("'normal.target'", actual)
4441+
43974442
def make_module(self, code):
43984443
tmpdir = Path(tempfile.mkdtemp())
43994444
self.addCleanup(shutil.rmtree, tmpdir)

Lib/traceback.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1605,25 +1605,18 @@ def _check_for_nested_attribute(obj, wrong_name, attrs):
16051605
"""Check if any attribute of obj has the wrong_name as a nested attribute.
16061606
16071607
Returns the first nested attribute suggestion found, or None.
1608-
Limited to checking 20 attributes and returning up to 5 suggestions.
1608+
Limited to checking 20 attributes.
16091609
"""
1610-
nested_suggestions = []
1611-
max_nested_suggestions = 5
1612-
16131610
# Check for nested attributes (only one level deep)
16141611
attrs_to_check = [x for x in attrs if not x.startswith('_')][:20] # Limit number of attributes to check
16151612
for attr_name in attrs_to_check:
1616-
try:
1613+
with suppress(Exception):
16171614
attr_obj = getattr(obj, attr_name)
16181615
# Check if the nested attribute has the wrong_name
16191616
if hasattr(attr_obj, wrong_name):
1620-
nested_suggestions.append(f"{attr_name}.{wrong_name}")
1621-
if len(nested_suggestions) >= max_nested_suggestions:
1622-
break
1623-
except:
1624-
pass
1617+
return f"{attr_name}.{wrong_name}"
16251618

1626-
return nested_suggestions[0] if nested_suggestions else None
1619+
return None
16271620

16281621

16291622
def _compute_suggestion_error(exc_value, tb, wrong_name):
@@ -1721,12 +1714,10 @@ def _compute_suggestion_error(exc_value, tb, wrong_name):
17211714

17221715
# If no direct attribute match found, check for nested attributes
17231716
if not suggestion and isinstance(exc_value, AttributeError):
1724-
try:
1717+
with suppress(Exception):
17251718
nested_suggestion = _check_for_nested_attribute(exc_value.obj, wrong_name, d)
17261719
if nested_suggestion:
17271720
return nested_suggestion
1728-
except:
1729-
pass
17301721

17311722
return suggestion
17321723

0 commit comments

Comments
 (0)