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

1# coding: utf-8

2"""# Fuzzy completion

3

4 The 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

14 import string

15 from fnmatch import fnmatch

16 from pathlib import Path

17

18 from .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

25 def 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

36 def 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

50 def 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

78 def 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

96 def 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)