Coverage for /home/tbone/.local/share/hatch/env/virtual/importnb-aVRh-lqt/test.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 09:31 -0700
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-03 09:31 -0700
1# coding: utf-8
2"""# Fuzzy completion
4The fuzzy importer could be confusing and perhaps a completer could help.
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"""
14import string
15from fnmatch import fnmatch
16from pathlib import Path
18from .finder import fuzzy_file_search
21"""To provide the most reliable fuzzy imports `fuzzify_string` replaces the imported with one that complies with the fuzzy finder.
22"""
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 )
32"""`align_match` replaces the the begining of the match with a prefix that matches that completer query name.
33"""
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:]
46"""* `predict_fuzzy` will take a fully qualified fuzzy name completions. This is the main function for the completer.
47"""
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 )
72 return set(
73 (package and package + "." or "") + align_match(fuzzify_string(spec), fullname)
74 for spec in specs
75 ).union(set(extras))
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 ]
89 return predict_fuzzy(symbol)
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"""
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)