Skip to content

Commit 57a4d39

Browse files
committed
Consolidate cross-language tests, shorten raw-message hints
Address review feedback from @vstinner: - Merge 14 individual test_cross_language_* methods into a single parameterized test_cross_language using subTest - Shorten raw-message hints: "Use 'x in list'." and "Use d[k] = v." - Fix pre-existing levenshtein priority test assertion - Update whatsnew entry to match shortened hint text
1 parent 99e106a commit 57a4d39

File tree

3 files changed

+27
-58
lines changed

3 files changed

+27
-58
lines changed

Doc/whatsnew/3.15.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ Improved error messages
445445
>>> {}.put("a", 1) # doctest: +ELLIPSIS
446446
Traceback (most recent call last):
447447
...
448-
AttributeError: 'dict' object has no attribute 'put'. Use d[k] = v for item assignment.
448+
AttributeError: 'dict' object has no attribute 'put'. Use d[k] = v.
449449

450450
(Contributed by Matt Van Horn in :gh:`146406`.)
451451

Lib/test/test_traceback.py

Lines changed: 24 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -4564,68 +4564,37 @@ def __init__(self):
45644564
actual = self.get_suggestion(Outer(), 'target')
45654565
self.assertIn("'.normal.target'", actual)
45664566

4567-
def test_cross_language_list_push_suggests_append(self):
4567+
def test_cross_language(self):
4568+
cases = [
4569+
# (obj, attr, expected_substring)
4570+
([], 'push', "'.append'"),
4571+
([], 'concat', "'.extend'"),
4572+
([], 'addAll', "'.extend'"),
4573+
([], 'contains', "Use 'x in list'."),
4574+
([], 'add', "Did you mean to use a 'set' object?"),
4575+
('', 'toUpperCase', "'.upper'"),
4576+
('', 'toLowerCase', "'.lower'"),
4577+
('', 'trimStart', "'.lstrip'"),
4578+
('', 'trimEnd', "'.rstrip'"),
4579+
({}, 'keySet', "'.keys'"),
4580+
({}, 'entrySet', "'.items'"),
4581+
({}, 'entries', "'.items'"),
4582+
({}, 'putAll', "'.update'"),
4583+
({}, 'put', "d[k] = v"),
4584+
]
4585+
for obj, attr, expected in cases:
4586+
with self.subTest(type=type(obj).__name__, attr=attr):
4587+
actual = self.get_suggestion(obj, attr)
4588+
self.assertIn(expected, actual)
4589+
# push hint should not repeat the wrong attribute name
45684590
actual = self.get_suggestion([], 'push')
4569-
self.assertIn("'.append'", actual)
45704591
self.assertNotIn("instead of", actual)
45714592

4572-
def test_cross_language_list_concat_suggests_extend(self):
4573-
actual = self.get_suggestion([], 'concat')
4574-
self.assertIn("'.extend'", actual)
4575-
4576-
def test_cross_language_list_addAll_suggests_extend(self):
4577-
actual = self.get_suggestion([], 'addAll')
4578-
self.assertIn("'.extend'", actual)
4579-
4580-
def test_cross_language_list_contains_suggests_in(self):
4581-
actual = self.get_suggestion([], 'contains')
4582-
self.assertIn("Use 'x in list'", actual)
4583-
4584-
def test_cross_language_list_add_suggests_set(self):
4585-
actual = self.get_suggestion([], 'add')
4586-
self.assertIn("Did you mean to use a 'set' object?", actual)
4587-
4588-
def test_cross_language_str_toUpperCase_suggests_upper(self):
4589-
actual = self.get_suggestion('', 'toUpperCase')
4590-
self.assertIn("'.upper'", actual)
4591-
4592-
def test_cross_language_str_toLowerCase_suggests_lower(self):
4593-
actual = self.get_suggestion('', 'toLowerCase')
4594-
self.assertIn("'.lower'", actual)
4595-
4596-
def test_cross_language_str_trimStart_suggests_lstrip(self):
4597-
actual = self.get_suggestion('', 'trimStart')
4598-
self.assertIn("'.lstrip'", actual)
4599-
4600-
def test_cross_language_str_trimEnd_suggests_rstrip(self):
4601-
actual = self.get_suggestion('', 'trimEnd')
4602-
self.assertIn("'.rstrip'", actual)
4603-
4604-
def test_cross_language_dict_keySet_suggests_keys(self):
4605-
actual = self.get_suggestion({}, 'keySet')
4606-
self.assertIn("'.keys'", actual)
4607-
4608-
def test_cross_language_dict_entrySet_suggests_items(self):
4609-
actual = self.get_suggestion({}, 'entrySet')
4610-
self.assertIn("'.items'", actual)
4611-
4612-
def test_cross_language_dict_putAll_suggests_update(self):
4613-
actual = self.get_suggestion({}, 'putAll')
4614-
self.assertIn("'.update'", actual)
4615-
4616-
def test_cross_language_dict_entries_suggests_items(self):
4617-
actual = self.get_suggestion({}, 'entries')
4618-
self.assertIn("'.items'", actual)
4619-
4620-
def test_cross_language_dict_put_suggests_bracket(self):
4621-
actual = self.get_suggestion({}, 'put')
4622-
self.assertIn("d[k] = v", actual)
4623-
46244593
def test_cross_language_levenshtein_takes_priority(self):
46254594
# Levenshtein catches trim->strip and indexOf->index before
46264595
# the cross-language table is consulted
46274596
actual = self.get_suggestion('', 'trim')
4628-
self.assertIn("'.strip'", actual)
4597+
self.assertIn("strip", actual)
46294598

46304599
def test_cross_language_no_hint_for_unknown_attr(self):
46314600
actual = self.get_suggestion([], 'completely_unknown_method')

Lib/traceback.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1673,7 +1673,7 @@ def print(self, *, file=None, chain=True, **kwargs):
16731673
(list, "concat"): ("extend", False),
16741674
# list -- Java/C# equivalents
16751675
(list, "addAll"): ("extend", False),
1676-
(list, "contains"): ("Use 'x in list' to check membership.", True),
1676+
(list, "contains"): ("Use 'x in list'.", True),
16771677
# list -- wrong-type suggestion more likely means the user expected a set
16781678
(list, "add"): ("Did you mean to use a 'set' object?", True),
16791679
# str -- JavaScript equivalents
@@ -1686,7 +1686,7 @@ def print(self, *, file=None, chain=True, **kwargs):
16861686
(dict, "entrySet"): ("items", False),
16871687
(dict, "entries"): ("items", False),
16881688
(dict, "putAll"): ("update", False),
1689-
(dict, "put"): ("Use d[k] = v for item assignment.", True),
1689+
(dict, "put"): ("Use d[k] = v.", True),
16901690
}
16911691

16921692

0 commit comments

Comments
 (0)