Created
October 23, 2014 16:24
-
-
Save dutc/3f2c79048d95287be138 to your computer and use it in GitHub Desktop.
Did you mean? in Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
from re import search | |
from itertools import chain | |
# levenshtein | |
def distance(x, y): | |
if not len(x): return len(y) | |
if not len(y): return len(x) | |
return min(distance(x[1:], y[1:]) + (x[0] != y[0]), distance(x[1:], y) + 1, distance(x, y[1:]) + 1) | |
import sys | |
def didyoumean(exc_type, value, traceback, excepthook=sys.excepthook): | |
if issubclass(exc_type, AttributeError): | |
terms = search("'(\w+)' object has no attribute '(\w+)'", value.message) | |
if terms: | |
type_name, attr = terms.groups() | |
type_obj = next((t for t in | |
chain(traceback.tb_frame.f_locals.values(), | |
traceback.tb_frame.f_globals.values()) | |
if type_name == type(t).__name__), None) | |
if type_obj: | |
candidate = min(dir(type_obj), key=lambda x: distance(attr, x)) | |
value = AttributeError(value.message + | |
'\nMaybe you meant: {}.{}'.format(type_name, candidate)) | |
return excepthook(exc_type, value, traceback) | |
sys.excepthook = didyoumean | |
class Foo(object): | |
def bar(self): | |
pass | |
if __name__ == '__main__': | |
foo = Foo() | |
foo.baz |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# levenshtein | |
def distance(x, y): | |
if not len(x): return len(y) | |
if not len(y): return len(x) | |
return min(distance(x[1:], y[1:]) + (x[0] != y[0]), distance(x[1:], y) + 1, distance(x, y[1:]) + 1) | |
class Foo(object): | |
def bar(self): | |
pass | |
def __getattr__(self, attr): | |
if not attr.startswith('__'): | |
candidate = min(dir(self), key=lambda x: distance(attr, x)) | |
raise AttributeError('Did you mean? .{}'.format(candidate)) | |
if __name__ == '__main__': | |
foo = Foo() | |
foo.baz |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment