Coverage for /home/tbone/.local/share/hatch/env/virtual/importnb-aVRh-lqt/test-legacy.stdlib/lib/python3.9/site-packages/importnb/completer.py: 0%

47 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-10-03 10:53 -0700

1# coding: utf-8 

2"""# Fuzzy completion 

3 

4The fuzzy importer could be confusing and perhaps a completer could help. 

5 

6 

7 >>> ip = __import__("IPython").get_ipython(); load_ipython_extension(ip) 

8 >>> assert ip.complete('importnb.__pleter', 'import importnb.__pleter')[1] 

9 >>> assert ip.complete('__find__', 'import __find__')[1] 

10 >>> assert ip.complete('IPy', '\timport IPy')[1] 

11 >>> assert ip.complete('_______________plet__', 'from importnb import _______________plet__')[1] 

12""" 

13 

14import string 

15from fnmatch import fnmatch 

16from pathlib import Path 

17 

18from .finder import fuzzy_file_search 

19 

20 

21"""To provide the most reliable fuzzy imports `fuzzify_string` replaces the imported with one that complies with the fuzzy finder. 

22""" 

23 

24 

25def fuzzify_string(str): 

26 return (str[0] in string.ascii_letters + "_" and str[0] or "_") + "".join( 

27 letter if letter in string.ascii_letters + "_" + string.digits else "_" 

28 for letter in str[1:] 

29 ) 

30 

31 

32"""`align_match` replaces the the begining of the match with a prefix that matches that completer query name. 

33""" 

34 

35 

36def align_match(match, prefix, *, i=0): 

37 pattern = prefix.replace("__", "*").replace("_", "?").strip() 

38 for i in range(len(match)): 

39 if fnmatch(match[:i], pattern): 

40 break 

41 else: 

42 i += 1 

43 return prefix + match[i:] 

44 

45 

46"""* `predict_fuzzy` will take a fully qualified fuzzy name completions. This is the main function for the completer. 

47""" 

48 

49 

50def predict_fuzzy(fullname): 

51 package, paths, specs, extras = "", [], [], [] 

52 if "." in fullname: 

53 package, fullname = fullname.rsplit(".", 1) 

54 fullname = fullname.strip() 

55 try: 

56 module = __import__("importlib").import_module(package) 

57 paths.append(Path(module.__file__).parent) 

58 extras = [object for object in dir(module) if object.startswith("fullname")] 

59 except: 

60 ... 

61 else: 

62 paths = map(Path, __import__("sys").path) 

63 query = fullname 

64 while not query.endswith("__"): 

65 query += "_" 

66 for path in paths: 

67 specs.extend( 

68 str(object.relative_to(path).with_suffix("")) 

69 for object in fuzzy_file_search(path, query) 

70 ) 

71 

72 return set( 

73 (package and package + "." or "") + align_match(fuzzify_string(spec), fullname) 

74 for spec in specs 

75 ).union(set(extras)) 

76 

77 

78def fuzzy_complete_event(self, event): 

79 event.line = event.line.lstrip() 

80 symbol = event.symbol 

81 if event.line.startswith("from"): 

82 package = event.line.split(" import ", 1)[0].lstrip().lstrip("from").lstrip() 

83 if " import" in event.line: 

84 symbol = (package + "." + symbol).lstrip(".") 

85 return [ 

86 object.lstrip(package).lstrip(".") for object in predict_fuzzy(symbol) 

87 ] 

88 

89 return predict_fuzzy(symbol) 

90 

91 

92"""* The extension adds the new fuzzy completer. Our completer has a higher priority than the default completers. Since we stripped the leading whitespace from the completion line event; the extension will permit completion on tabbed lines. 

93""" 

94 

95 

96def load_ipython_extension(ip): 

97 ip.set_hook( 

98 "complete_command", fuzzy_complete_event, str_key="aimport", priority=25 

99 ) 

100 ip.set_hook("complete_command", fuzzy_complete_event, str_key="import", priority=25) 

101 ip.set_hook( 

102 "complete_command", fuzzy_complete_event, str_key="%reload_ext", priority=25 

103 ) 

104 ip.set_hook( 

105 "complete_command", fuzzy_complete_event, str_key="%load_ext", priority=25 

106 ) 

107 ip.set_hook("complete_command", fuzzy_complete_event, str_key="from", priority=25)