Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions Lib/test/test_traceback.py
Original file line number Diff line number Diff line change
Expand Up @@ -4355,6 +4355,43 @@ class DelattrSuggestionTests(BaseSuggestionTests):
attr_function = delattr


class SetattrSuggestionTests(SuggestionFormattingTestMixin):
def get_suggestion(self, obj, attr_name=None):
if attr_name is not None:
def callable():
setattr(obj, attr_name, None)
else:
callable = obj
result_lines = self.get_exception(callable, slice_start=-1, slice_end=None)
return result_lines[0]

def test_property_no_setter_suggests_similar(self):
class A:
@property
def computed_a(self):
return 1

@property
def computed_b(self):
return 2

@computed_b.setter
def computed_b(self, val):
pass

actual = self.get_suggestion(A(), 'computed_a')
self.assertIn("Did you mean '.computed_b'", actual)

def test_property_no_setter_no_false_suggestion(self):
class A:
@property
def computed_a(self):
return 1

actual = self.get_suggestion(A(), 'computed_a')
self.assertNotIn("Did you mean", actual)


class SuggestionFormattingTestBase(SuggestionFormattingTestMixin):
def test_attribute_error_with_failing_dict(self):
class T:
Expand Down Expand Up @@ -5178,6 +5215,30 @@ class CPythonDelattrSuggestionFormattingTests(
internal traceback printing.
"""


class PurePythonSetattrSuggestionFormattingTests(
PurePythonExceptionFormattingMixin,
SetattrSuggestionTests,
unittest.TestCase,
):
"""
Tests for "Did you mean" suggestions when setting a read-only property,
using the pure Python traceback implementation.
"""


@cpython_only
class CPythonSetattrSuggestionFormattingTests(
CAPIExceptionFormattingMixin,
SetattrSuggestionTests,
unittest.TestCase,
):
"""
Same set of tests (for attribute setting) but with Python's internal
traceback printing.
"""


class MiscTest(unittest.TestCase):

def test_all(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:exc:`AttributeError` raised when setting a read-only property now includes
"Did you mean" suggestions, matching the behaviour already present for
attribute lookup and deletion.
3 changes: 3 additions & 0 deletions Objects/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -2061,6 +2061,9 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
f = Py_TYPE(descr)->tp_descr_set;
if (f != NULL) {
res = f(descr, obj, value);
if (res < 0) {
_PyObject_SetAttributeErrorContext(obj, name);
}
goto done;
}
}
Expand Down
Loading