Skip to content

Commit 6d05cc3

Browse files
committed
Introduce pyls.extraSysPath configuration
Before this commit, there is no way to specify extra "sys path" for completion, lint-ing, and so on: passing it via PYTHONPATH might cause unintentional side effect for pyls itself. In order to explicitly specify extra "sys path", this commit introduces pyls.extraSysPath configuration, and adds its value to extra_sys_path at Document construction. After this commit, Document.sys_path() returns the list of paths in the order below. 1. source root(s) in the workspace 2. extra sys path (introduced by this commit) 3. sys.path of Python runtime pyls.extraSysPath configuration accepts any path, even if it referring outside of the workspace. BTW, paths configured via pyls.plugins.jedi.extra_paths will be added after values above at Document.jedi_script(). Therefore, pyls.extraSysPath configuration is also useful at putting paths at the front of runtime sys.path for jedi plugin.
1 parent 6b58a1e commit 6d05cc3

File tree

4 files changed

+53
-1
lines changed

4 files changed

+53
-1
lines changed

pyls/config/pyls_conf.py

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
PROJECT_CONFIGS = ['setup.cfg', 'tox.ini']
99

1010
OPTIONS = [
11+
('extra-sys-path', 'extraSysPath', list),
1112
('source-roots', 'sourceRoots', list),
1213
]
1314

pyls/workspace.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,12 @@ def source_roots(self, document_path):
131131
return list(set((os.path.dirname(project_file) for project_file in files))) or [self._root_path]
132132

133133
def _create_document(self, doc_uri, source=None, version=None):
134+
# extraSysPath allows path to outside workspace
135+
extra_sys_path = self.normalize_config_paths('extraSysPath', inside_only=False)
134136
path = uris.to_fs_path(doc_uri)
135137
return Document(
136138
doc_uri, source=source, version=version,
137-
extra_sys_path=self.source_roots(path),
139+
extra_sys_path=self.source_roots(path) + extra_sys_path,
138140
rope_project_builder=self._rope_project_builder,
139141
config=self._config, workspace=self,
140142
)

test/test_workspace.py

+40
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,43 @@ def test_source_roots_config(tmpdir, metafile):
169169
assert full_path not in sys_path # check for safety
170170
else:
171171
assert norm_path in sys_path
172+
173+
174+
@pytest.mark.parametrize('metafile', ['setup.cfg', 'tox.ini', None])
175+
def test_extra_sys_path_config(tmpdir, metafile):
176+
root_path = str(tmpdir)
177+
178+
extra_sys_path = ['/abs/path', '../relative/path']
179+
180+
if metafile:
181+
# configured by metafile at pyls startup
182+
with open(os.path.join(root_path, metafile), 'w+') as f:
183+
f.write('[pyls]\nextra-sys-path=\n %s\n' %
184+
',\n '.join(extra_sys_path))
185+
186+
pyls = PythonLanguageServer(StringIO, StringIO)
187+
pyls.m_initialize(
188+
processId=1,
189+
rootUri=uris.from_fs_path(root_path),
190+
initializationOptions={}
191+
)
192+
193+
if not metafile:
194+
# configured by client via LSP after pyls startup
195+
pyls.m_workspace__did_change_configuration({
196+
'pyls': {'extraSysPath': extra_sys_path},
197+
})
198+
199+
test_uri = uris.from_fs_path(os.path.join(root_path, 'hello/test.py'))
200+
pyls.workspace.put_document(test_uri, 'assert True')
201+
test_doc = pyls.workspace.get_document(test_uri)
202+
203+
# apply os.path.normcase() on paths below, because case-sensitive
204+
# comparison on Windows causes unintentional failure for case
205+
# instability around drive letter
206+
207+
sys_path = [os.path.normcase(p) for p in test_doc.sys_path()]
208+
for raw_path in extra_sys_path:
209+
full_path = os.path.join(root_path, raw_path)
210+
norm_path = os.path.normcase(os.path.normpath(full_path))
211+
assert norm_path in sys_path

vscode-client/package.json

+9
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@
3535
},
3636
"uniqueItems": true
3737
},
38+
"pyls.extraSysPath": {
39+
"type": "array",
40+
"default": [],
41+
"description": "List of extra paths to find packages.",
42+
"items": {
43+
"type": "string"
44+
},
45+
"uniqueItems": true
46+
},
3847
"pyls.sourceRoots": {
3948
"type": "array",
4049
"default": [],

0 commit comments

Comments
 (0)