Skip to content

Commit 6d58cdc

Browse files
committed
Address review feedback from @nedbat and @ZeroIntensity
- Shorten hint format to "Did you mean '.append'?" (drop redundant "instead of '.push'" since the error already names the attribute) - Add dict.put and list.contains entries suggesting language constructs (dict[key] = value, x in list) per @ZeroIntensity's review - Replace suppress(Exception) with direct call (function is safe) - Link to GH issue instead of Discourse thread in comment - Drop column alignment in hint table entries - Trim NEWS entry last sentence
1 parent aecaacb commit 6d58cdc

File tree

3 files changed

+28
-19
lines changed

3 files changed

+28
-19
lines changed

Lib/test/test_traceback.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4567,6 +4567,7 @@ def __init__(self):
45674567
def test_cross_language_list_push_suggests_append(self):
45684568
actual = self.get_suggestion([], 'push')
45694569
self.assertIn("'.append'", actual)
4570+
self.assertNotIn("instead of", actual)
45704571

45714572
def test_cross_language_list_concat_suggests_extend(self):
45724573
actual = self.get_suggestion([], 'concat')
@@ -4576,6 +4577,10 @@ def test_cross_language_list_addAll_suggests_extend(self):
45764577
actual = self.get_suggestion([], 'addAll')
45774578
self.assertIn("'.extend'", actual)
45784579

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+
45794584
def test_cross_language_list_add_suggests_set(self):
45804585
actual = self.get_suggestion([], 'add')
45814586
self.assertIn("Did you mean to use a set?", actual)
@@ -4608,6 +4613,10 @@ def test_cross_language_dict_putAll_suggests_update(self):
46084613
actual = self.get_suggestion({}, 'putAll')
46094614
self.assertIn("'.update'", actual)
46104615

4616+
def test_cross_language_dict_put_suggests_bracket(self):
4617+
actual = self.get_suggestion({}, 'put')
4618+
self.assertIn("dict[key] = value", actual)
4619+
46114620
def test_cross_language_levenshtein_takes_priority(self):
46124621
# Levenshtein catches trim->strip and indexOf->index before
46134622
# the cross-language table is consulted

Lib/traceback.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,10 +1154,9 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None,
11541154
else:
11551155
self._str += f". Did you mean '.{suggestion}' ({suggestion!a}) instead of '.{wrong_name}' ({wrong_name!a})?"
11561156
elif hasattr(exc_value, 'obj'):
1157-
with suppress(Exception):
1158-
hint = _get_cross_language_hint(exc_value.obj, wrong_name)
1159-
if hint:
1160-
self._str += f". {hint}"
1157+
hint = _get_cross_language_hint(exc_value.obj, wrong_name)
1158+
if hint:
1159+
self._str += f". {hint}"
11611160
elif exc_type and issubclass(exc_type, NameError) and \
11621161
getattr(exc_value, "name", None) is not None:
11631162
wrong_name = getattr(exc_value, "name", None)
@@ -1669,25 +1668,27 @@ def print(self, *, file=None, chain=True, **kwargs):
16691668
# If the suggestion is a Python method name, the standard "Did you mean"
16701669
# format is used. If it contains a space, it's rendered as a full hint.
16711670
#
1672-
# See https://discuss.python.org/t/106632 for the design discussion.
1671+
# See https://github.com/python/cpython/issues/146406 for the design discussion.
16731672
_CROSS_LANGUAGE_HINTS = {
16741673
# list -- JavaScript/Ruby equivalents
1675-
(list, "push"): "append",
1676-
(list, "concat"): "extend",
1674+
(list, "push"): "append",
1675+
(list, "concat"): "extend",
16771676
# list -- Java/C# equivalents
1678-
(list, "addAll"): "extend",
1677+
(list, "addAll"): "extend",
1678+
(list, "contains"): "Use 'x in list' to check membership",
16791679
# list -- wrong-type suggestion (per Serhiy Storchaka, Terry Reedy,
16801680
# Paul Moore: list.add() more likely means the user expected a set)
1681-
(list, "add"): "Did you mean to use a set? Sets have an .add() method",
1681+
(list, "add"): "Did you mean to use a set? Sets have an .add() method",
16821682
# str -- JavaScript equivalents
16831683
(str, "toUpperCase"): "upper",
16841684
(str, "toLowerCase"): "lower",
1685-
(str, "trimStart"): "lstrip",
1686-
(str, "trimEnd"): "rstrip",
1685+
(str, "trimStart"): "lstrip",
1686+
(str, "trimEnd"): "rstrip",
16871687
# dict -- Java equivalents
1688-
(dict, "keySet"): "keys",
1689-
(dict, "entrySet"): "items",
1690-
(dict, "putAll"): "update",
1688+
(dict, "keySet"): "keys",
1689+
(dict, "entrySet"): "items",
1690+
(dict, "putAll"): "update",
1691+
(dict, "put"): "Use dict[key] = value for item assignment",
16911692
# Note: indexOf, trim, and getOrDefault are not included because
16921693
# Levenshtein distance already catches them (indexOf->index,
16931694
# trim->strip, getOrDefault->setdefault).
@@ -1768,8 +1769,8 @@ def _get_cross_language_hint(obj, wrong_name):
17681769
if ' ' in hint:
17691770
# Full custom hint (e.g., wrong-type suggestion for list.add)
17701771
return hint
1771-
# Direct method equivalent -- format like Levenshtein suggestions
1772-
return f"Did you mean '.{hint}' instead of '.{wrong_name}'?"
1772+
# Direct method equivalent
1773+
return f"Did you mean '.{hint}'?"
17731774

17741775

17751776
def _get_safe___dir__(obj):
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
Cross-language method suggestions are now shown for :exc:`AttributeError` on
22
builtin types when the existing Levenshtein-based suggestions find no match.
3-
For example, ``[].push()`` now suggests ``append`` (JavaScript), and
4-
``"".toUpperCase()`` suggests ``upper``. The ``list.add()`` case suggests
5-
using a set instead, following feedback from the community discussion.
3+
For example, ``[].push()`` now suggests ``append`` and
4+
``"".toUpperCase()`` suggests ``upper``.

0 commit comments

Comments
 (0)