A completer for Python import statements. Examples: - import - import foo - import foo. - import foo as bar, baz - from - from foo - from foo import - from foo import bar - from f
| 49 | |
| 50 | |
| 51 | class ModuleCompleter: |
| 52 | """A completer for Python import statements. |
| 53 | |
| 54 | Examples: |
| 55 | - import <tab> |
| 56 | - import foo<tab> |
| 57 | - import foo.<tab> |
| 58 | - import foo as bar, baz<tab> |
| 59 | |
| 60 | - from <tab> |
| 61 | - from foo<tab> |
| 62 | - from foo import <tab> |
| 63 | - from foo import bar<tab> |
| 64 | - from foo import (bar as baz, qux<tab> |
| 65 | """ |
| 66 | |
| 67 | def __init__(self, namespace: Mapping[str, Any] | None = None) -> None: |
| 68 | self.namespace = namespace or {} |
| 69 | self._global_cache: list[pkgutil.ModuleInfo] = [] |
| 70 | self._failed_imports: set[str] = set() |
| 71 | self._curr_sys_path: list[str] = sys.path[:] |
| 72 | self._stdlib_path = os.path.dirname(importlib.__path__[0]) |
| 73 | |
| 74 | def get_completions(self, line: str) -> tuple[list[str], CompletionAction | None] | None: |
| 75 | """Return the next possible import completions for 'line'. |
| 76 | |
| 77 | For attributes completion, if the module to complete from is not |
| 78 | imported, also return an action (prompt + callback to run if the |
| 79 | user press TAB again) to import the module. |
| 80 | """ |
| 81 | result = ImportParser(line).parse() |
| 82 | if not result: |
| 83 | return None |
| 84 | try: |
| 85 | return self.complete(*result) |
| 86 | except Exception: |
| 87 | # Some unexpected error occurred, make it look like |
| 88 | # no completions are available |
| 89 | return [], None |
| 90 | |
| 91 | def complete(self, from_name: str | None, name: str | None) -> tuple[list[str], CompletionAction | None]: |
| 92 | if from_name is None: |
| 93 | # import x.y.z<tab> |
| 94 | assert name is not None |
| 95 | path, prefix = self.get_path_and_prefix(name) |
| 96 | modules = self.find_modules(path, prefix) |
| 97 | return [self.format_completion(path, module) for module in modules], None |
| 98 | |
| 99 | if name is None: |
| 100 | # from x.y.z<tab> |
| 101 | path, prefix = self.get_path_and_prefix(from_name) |
| 102 | modules = self.find_modules(path, prefix) |
| 103 | return [self.format_completion(path, module) for module in modules], None |
| 104 | |
| 105 | # from x.y import z<tab> |
| 106 | submodules = self.find_modules(from_name, name) |
| 107 | attributes, action = self.find_attributes(from_name, name) |
| 108 | return sorted({*submodules, *attributes}), action |
no outgoing calls
searching dependent graphs…