Skip to content

Commit 95bffde

Browse files
committed
non blocking index build
1 parent 71b8385 commit 95bffde

File tree

2 files changed

+45
-16
lines changed

2 files changed

+45
-16
lines changed

pyls/plugins/importmagic_lint.py

+38-16
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import logging
33
import re
44
import sys
5+
from concurrent.futures import ThreadPoolExecutor
56
import importmagic
67
from pyls import hookimpl, lsp, _utils
78

@@ -15,22 +16,37 @@
1516
UNRES_RE = re.compile(r"Unresolved import '(?P<unresolved>[\w.]+)'")
1617
UNREF_RE = re.compile(r"Unreferenced import '(?P<unreferenced>[\w.]+)'")
1718

18-
_index_cache = {}
19+
_index_cache = None
1920

2021

21-
def _get_index(sys_path):
22+
def _build_index(paths):
2223
"""Build index of symbols from python modules.
23-
Cache the index so we don't build it multiple times unnecessarily.
2424
"""
25-
key = tuple(sys_path)
26-
if key not in _index_cache:
27-
log.info("Started building importmagic index")
28-
index = importmagic.SymbolIndex()
29-
# The build tend to be noisy
30-
index.build_index(paths=sys_path)
31-
_index_cache[key] = index
32-
log.info("Finished building importmagic index")
33-
return _index_cache[key]
25+
log.info("Started building importmagic index")
26+
index = importmagic.SymbolIndex()
27+
index.build_index(paths=paths)
28+
log.info("Finished building importmagic index")
29+
return index
30+
31+
32+
def _cache_index_callback(future):
33+
global _index_cache
34+
# Cache the index
35+
_index_cache = future.result()
36+
37+
38+
def _get_index():
39+
"""Get the cached index if built and index project files on each call.
40+
Return an empty index if not built yet.
41+
"""
42+
# Index haven't been built yet
43+
if _index_cache is None:
44+
return importmagic.SymbolIndex()
45+
46+
# Index project files
47+
# TODO(youben) index project files
48+
#index.build_index(paths=[])
49+
return _index_cache
3450

3551

3652
def _get_imports_list(source, index=None):
@@ -46,6 +62,13 @@ def _get_imports_list(source, index=None):
4662
return imported
4763

4864

65+
@hookimpl
66+
def pyls_initialize():
67+
pool = ThreadPoolExecutor()
68+
builder = pool.submit(_build_index, (sys.path))
69+
builder.add_done_callback(_cache_index_callback)
70+
71+
4972
@hookimpl
5073
def pyls_commands():
5174
return [ADD_IMPORT_COMMAND, REMOVE_IMPORT_COMMAND]
@@ -125,7 +148,7 @@ def pyls_lint(document):
125148

126149

127150
@hookimpl
128-
def pyls_code_actions(config, document):
151+
def pyls_code_actions(config, document, context):
129152
"""Build a list of actions to be suggested to the user. Each action follow this format:
130153
{
131154
'title': 'importmagic',
@@ -146,9 +169,8 @@ def pyls_code_actions(config, document):
146169
log.debug("Got importmagic settings: %s", conf)
147170
importmagic.Imports.set_style(**{_utils.camel_to_underscore(k): v for k, v in conf.items()})
148171

149-
# Might be slow but is cached once built
150-
# TODO (youben): add project path for indexing
151-
index = _get_index(sys.path)
172+
# Get empty index while it's building so we don't block here
173+
index = _get_index()
152174
actions = []
153175

154176
diagnostics = pyls_lint(document)

test/plugins/test_importmagic_lint.py

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Copyright 2019 Palantir Technologies, Inc.
22
import tempfile
33
import os
4+
from time import sleep
45
from pyls import lsp, uris
56
from pyls.plugins import importmagic_lint
67
from pyls.workspace import Document
@@ -39,7 +40,11 @@ def test_importmagic_lint():
3940

4041
def test_importmagic_actions(config):
4142
try:
43+
importmagic_lint.pyls_initialize()
4244
name, doc = temp_document(DOC)
45+
while importmagic_lint._index_cache is None:
46+
# wait for the index to be ready
47+
sleep(1)
4348
actions = importmagic_lint.pyls_code_actions(config, doc)
4449
action = [a for a in actions if a['title'] == 'Import "time"'][0]
4550
arguments = action['arguments'][0]
@@ -51,3 +56,5 @@ def test_importmagic_actions(config):
5156

5257
finally:
5358
os.remove(name)
59+
60+
# TODO(youben) write test for remove action

0 commit comments

Comments
 (0)