8000 [WIP] Heuristic for better error messages by Carreau · Pull Request #9073 · ipython/ipython · GitHub
[go: up one dir, main page]

Skip to content

[WIP] Heuristic for better error messages #9073

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
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
0