Skip to content
Closed
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
49 changes: 49 additions & 0 deletions IPython/core/ultratb.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
import inspect
import keyword
import linecache
import difflib
import os
import pydoc
import re
Expand Down Expand Up @@ -1028,7 +1029,55 @@ def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_con

if records is None:
return ""

###
# record heuristics
reg = re.compile("([a-zA-Z_]+)\(\) got an unexpected keyword argument '(.+)'")
reg2 = re.compile("'([a-zA-Z_]+)' object has no attribute '(.+)'")
# figure out what to do on len(args) > 1
try:
match = reg.match(evalue.args[0])
if (etype == 'TypeError') and match:
last_record = records[-1]
function, kw = match.groups()
func = last_record[0].f_locals.get(function, None)
if not func:
func = last_record[0].f_globals.get(function, None)
signature = inspect.signature(func)
matches = difflib.get_close_matches(kw, signature.parameters.keys(), 3, 0.3)
if len(matches) == 1:
evalue.args = (evalue.args[0]+". Did you mean '%s' ? " % matches[0], )
elif len(matches) > 1:
evalue.args = (evalue.args[0]+'. Did you mean one of %s ? ' % ', '.join(map(lambda x : "'"+x+"'", matches)), )
match = reg2.match(evalue.args[0])
except Exception:
pass
try:
if (etype == 'AttributeError') and match:
last_record = records[-1]
frame = last_record[0]
names = frame.f_code.co_names
typ, missing = match.groups()
for name in names:
obj = frame.f_locals.get(name, frame.f_globals.get(name, None))
# likely no the right object, but likely the right type.
if obj and type(obj).__name__ == typ and (name in last_record[4][0]):
matches = difflib.get_close_matches(missing, dir(obj), 3, 0.3)
if len(matches) == 1:
evalue.args = (evalue.args[0]+". Did you mean '%s', which belong to '%s' ? " % (matches[0], name), )
elif len(matches) > 1:
evalue.args = (evalue.args[0]+". Did you mean one of %s, which belong to '%s' ? " % ( ', '.join(map(lambda x : "'"+x+"'", matches)), name), )



except Exception:
pass





###
frames = self.format_records(records)

formatted_exception = self.format_exception(etype, evalue)
Expand Down