Skip to content

Commit

Permalink
Add suggestion for del/remove/discard #18
Browse files Browse the repository at this point in the history
  • Loading branch information
SylvainDe committed Dec 14, 2017
1 parent 78c0ba0 commit 67ac9ba
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 8 deletions.
11 changes: 8 additions & 3 deletions didyoumean/didyoumean_internal.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@

#: Almost synonyms methods that can be confused from one type to another
# To be completed
SYNONYMS_SETS = [set(['add', 'append']), set(['extend', 'update'])]
SYNONYMS_SETS = [
set(['add', 'append']),
set(['extend', 'update']),
set(['remove', 'discard', '__delitem__'])
]

#: Maximum number of files suggested
MAX_NB_FILES = 4
Expand Down Expand Up @@ -384,7 +388,6 @@ def get_attribute_suggestions(type_str, attribute, frame):
return itertools.chain(
suggest_attribute_as_builtin(attribute, type_str, frame),
suggest_attribute_alternative(attribute, type_str, attributes),
suggest_attribute_synonyms(attribute, attributes),
suggest_attribute_as_typo(attribute, attributes),
suggest_attribute_as_special_case(attribute))

Expand All @@ -401,6 +404,8 @@ def suggest_attribute_as_builtin(attribute, type_str, frame):

def suggest_attribute_alternative(attribute, type_str, attributes):
"""Suggest alternative to the non-found attribute."""
for s in suggest_attribute_synonyms(attribute, attributes):
yield s
is_iterable = '__iter__' in attributes or \
('__getitem__' in attributes and '__len__' in attributes)
if attribute == 'has_key' and '__contains__' in attributes:
Expand Down Expand Up @@ -450,7 +455,7 @@ def suggest_attribute_synonyms(attribute, attributes):
"""
for set_sub in SYNONYMS_SETS:
if attribute in set_sub:
for syn in set_sub & attributes:
for syn in sorted(set_sub & attributes):
yield quote(syn)


Expand Down
35 changes: 30 additions & 5 deletions didyoumean/didyoumean_sugg_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,26 @@ def test_wrongmethod2(self):
self.throws(bad_code, ATTRIBUTEERROR, sugg)
self.runs(good_code)

def test_wrongmethod3(self):
"""Should be 's.remove(42)' or 's.discard(42)'."""
code = 's = set([42, 43])\n{0}'
typo, good1, good2 = 'del s[42]', 's.remove(42)', 's.discard(42)'
bad_code, good_code1, good_code2 = format_str(code, typo, good1, good2)
suggs = ["'discard'", "'remove'", 'convert to list to edit the list']
self.throws(bad_code, OBJECTDOESNOTSUPPORT, suggs)
self.runs(good_code1)
self.runs(good_code2)

def test_wrongmethod4(self):
"""Should be 'del d[42]'."""
code = 'd = dict()\nd[42] = False\n{0}'
good, typo1, typo2 = 'del d[42]', 'd.remove(42)', 'd.discard(42)'
good_code, bad_code1, bad_code2 = format_str(code, good, typo1, typo2)
self.runs(good_code)
sugg = "'__delitem__'"
self.throws(bad_code1, ATTRIBUTEERROR, sugg)
self.throws(bad_code2, ATTRIBUTEERROR, sugg)

def test_hidden(self):
"""Accessing wrong string object."""
# NICE_TO_HAVE
Expand Down Expand Up @@ -1130,15 +1150,20 @@ def test_set_dict_comprehension(self):
"""{} creates a dict and not an empty set leading to errors."""
# NICE_TO_HAVE
before, after = before_and_after((2, 7))
suggs = {
'discard': "'__delitem__'",
'remove': "'__delitem__'",
}
for method in set(dir(set)) - set(dir(dict)):
if not method.startswith('__'): # boring suggestions
code = "a = {0}\na." + method
typo, dict1, dict2, sugg, set1 = format_str(
typo, dict1, dict2, good, set1 = format_str(
code, "{}", "dict()", "{0: 0}", "set()", "{0}")
self.throws(typo, ATTRIBUTEERROR)
self.throws(dict1, ATTRIBUTEERROR)
self.throws(dict2, ATTRIBUTEERROR)
self.runs(sugg)
sugg = suggs.get(method, None)
self.throws(typo, ATTRIBUTEERROR, sugg)
self.throws(dict1, ATTRIBUTEERROR, sugg)
self.throws(dict2, ATTRIBUTEERROR, sugg)
self.runs(good)
self.throws(set1, INVALIDSYNTAX, [], before)
self.runs(set1, after)

Expand Down

0 comments on commit 67ac9ba

Please sign in to comment.