Skip to content

Commit 15e19cd

Browse files
authored
Support python projects in subdirectories (#34)
* Create test for non-root syspath * Implement syspaths
1 parent 77e008c commit 15e19cd

4 files changed

Lines changed: 32 additions & 4 deletions

File tree

pyls/providers/base.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# Copyright 2017 Palantir Technologies, Inc.
22
import os
33
import jedi
4-
import sys
54

65

76
class BaseProvider(object):
@@ -23,7 +22,7 @@ def jedi_script(self, doc_uri, position=None):
2322
document = self.workspace.get_document(doc_uri)
2423

2524
path = None
26-
sys_path = list(sys.path) # TODO Load from config
25+
sys_path = self.workspace.syspath_for_document(document)
2726

2827
# If we're local, we can add ourselves to Python path and do clevererer things
2928
if self.workspace.is_local():

pyls/workspace.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Copyright 2017 Palantir Technologies, Inc.
22
import os
33
import re
4+
import sys
45
from urllib.parse import urlparse, urlunparse
56

67
# TODO: this is not the best e.g. we capture numbers
@@ -51,6 +52,17 @@ def get_uri_like(self, doc_uri, path):
5152
parts[2] = path
5253
return urlunparse([str(p) for p in parts])
5354

55+
def syspath_for_document(self, document):
56+
""" Construct a sensible sys path to use for the given document.
57+
58+
Since the workspace root may not be the root of the Python project we instead
59+
append the closest parent directory containing a setup.py file.
60+
"""
61+
files = self.find_config_files(document, ['setup.py']) or []
62+
path = [os.path.dirname(setup_py) for setup_py in files]
63+
path.extend(sys.path)
64+
return path
65+
5466
def _check_in_workspace(self, doc_uri):
5567
doc_path = urlparse(doc_uri).path
5668
if not os.path.commonprefix((self.root, doc_path)):

test/fixtures.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@
77

88

99
@pytest.fixture
10-
def pyls():
10+
def pyls(tmpdir):
1111
""" Return an initialized python LS """
1212
rfile = StringIO()
1313
wfile = StringIO()
1414
ls = PythonLanguageServer(rfile, wfile)
1515

1616
ls.m_initialize(
1717
processId=1,
18-
rootPath=os.path.dirname(__file__),
18+
rootPath=str(tmpdir),
1919
initializationOptions={}
2020
)
2121

test/test_workspace.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Copyright 2017 Palantir Technologies, Inc.
2+
import os
23
import pytest
4+
from pyls.workspace import Workspace
35

46
DOC_URI = 'file://' + __file__
57

@@ -34,3 +36,18 @@ def test_bad_get_document(pyls):
3436

3537
def test_uri_like(pyls):
3638
assert pyls.workspace.get_uri_like('file:///some-path', '/my/path') == 'file:///my/path'
39+
40+
41+
def test_non_root_project(pyls):
42+
repo_root = os.path.join(pyls.workspace.root, 'repo-root')
43+
os.mkdir(repo_root)
44+
project_root = os.path.join(repo_root, 'project-root')
45+
os.mkdir(project_root)
46+
47+
with open(os.path.join(project_root, 'setup.py'), 'w+') as f:
48+
f.write('# setup.py')
49+
50+
test_uri = 'file://' + os.path.join(project_root, 'hello/test.py')
51+
pyls.workspace.put_document(test_uri, 'assert True')
52+
test_doc = pyls.workspace.get_document(test_uri)
53+
assert project_root in pyls.workspace.syspath_for_document(test_doc)

0 commit comments

Comments
 (0)