diff --git a/pyls/providers/base.py b/pyls/providers/base.py index 5596bc2f..3e46cd5b 100644 --- a/pyls/providers/base.py +++ b/pyls/providers/base.py @@ -1,7 +1,6 @@ # Copyright 2017 Palantir Technologies, Inc. import os import jedi -import sys class BaseProvider(object): @@ -23,7 +22,7 @@ def jedi_script(self, doc_uri, position=None): document = self.workspace.get_document(doc_uri) path = None - sys_path = list(sys.path) # TODO Load from config + sys_path = self.workspace.syspath_for_document(document) # If we're local, we can add ourselves to Python path and do clevererer things if self.workspace.is_local(): diff --git a/pyls/workspace.py b/pyls/workspace.py index 5de22ce6..b5fd91f6 100644 --- a/pyls/workspace.py +++ b/pyls/workspace.py @@ -1,6 +1,7 @@ # Copyright 2017 Palantir Technologies, Inc. import os import re +import sys from urllib.parse import urlparse, urlunparse # TODO: this is not the best e.g. we capture numbers @@ -51,6 +52,17 @@ def get_uri_like(self, doc_uri, path): parts[2] = path return urlunparse([str(p) for p in parts]) + def syspath_for_document(self, document): + """ Construct a sensible sys path to use for the given document. + + Since the workspace root may not be the root of the Python project we instead + append the closest parent directory containing a setup.py file. + """ + files = self.find_config_files(document, ['setup.py']) or [] + path = [os.path.dirname(setup_py) for setup_py in files] + path.extend(sys.path) + return path + def _check_in_workspace(self, doc_uri): doc_path = urlparse(doc_uri).path if not os.path.commonprefix((self.root, doc_path)): diff --git a/test/fixtures.py b/test/fixtures.py index 199d0a7a..e386a601 100644 --- a/test/fixtures.py +++ b/test/fixtures.py @@ -7,7 +7,7 @@ @pytest.fixture -def pyls(): +def pyls(tmpdir): """ Return an initialized python LS """ rfile = StringIO() wfile = StringIO() @@ -15,7 +15,7 @@ def pyls(): ls.m_initialize( processId=1, - rootPath=os.path.dirname(__file__), + rootPath=str(tmpdir), initializationOptions={} ) diff --git a/test/test_workspace.py b/test/test_workspace.py index 777bb53a..f8f7e865 100644 --- a/test/test_workspace.py +++ b/test/test_workspace.py @@ -1,5 +1,7 @@ # Copyright 2017 Palantir Technologies, Inc. +import os import pytest +from pyls.workspace import Workspace DOC_URI = 'file://' + __file__ @@ -34,3 +36,18 @@ def test_bad_get_document(pyls): def test_uri_like(pyls): assert pyls.workspace.get_uri_like('file:///some-path', '/my/path') == 'file:///my/path' + + +def test_non_root_project(pyls): + repo_root = os.path.join(pyls.workspace.root, 'repo-root') + os.mkdir(repo_root) + project_root = os.path.join(repo_root, 'project-root') + os.mkdir(project_root) + + with open(os.path.join(project_root, 'setup.py'), 'w+') as f: + f.write('# setup.py') + + test_uri = 'file://' + os.path.join(project_root, 'hello/test.py') + pyls.workspace.put_document(test_uri, 'assert True') + test_doc = pyls.workspace.get_document(test_uri) + assert project_root in pyls.workspace.syspath_for_document(test_doc)