From cc9a4753616a15885813ae003ffcd6b1f144ad93 Mon Sep 17 00:00:00 2001 From: Sinkerine Date: Mon, 9 Sep 2019 01:49:56 -0700 Subject: [PATCH 1/2] Support pyenv virtualenv for LSP project roots The first path in Document._extra_sys_path will be used to find the virtual_env --- pyls/workspace.py | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/pyls/workspace.py b/pyls/workspace.py index 0ffab25a..29c6dac1 100644 --- a/pyls/workspace.py +++ b/pyls/workspace.py @@ -1,12 +1,14 @@ # Copyright 2017 Palantir Technologies, Inc. +import distutils.spawn import io import logging import os import re +import subprocess import jedi -from . import lsp, uris, _utils +from . import _utils, lsp, uris log = logging.getLogger(__name__) @@ -217,8 +219,45 @@ def sys_path(self): # Copy our extra sys path path = list(self._extra_sys_path) + sys_paths = set() # TODO(gatesn): #339 - make better use of jedi environments, they seem pretty powerful - environment = jedi.api.environment.get_cached_default_environment() - path.extend(environment.get_sys_path()) + # Support pyenv virtualenv for LSP project roots + if distutils.spawn.find_executable( + 'pyenv') and self._extra_sys_path and len( + self._extra_sys_path) > 0: + + class enter_pyenv_shell_env(): + def __init__(self): + self.env_pyenv_keys = ['PYENV_VERSION', 'PYENV_DIR'] + self.env_pyenv_old_vals = [] + + def __enter__(self): + # Remove ENV vars injected by pyenv + for key in self.env_pyenv_keys: + self.env_pyenv_old_vals.append(os.getenv(key)) + os.unsetenv(key) + + def __exit__(self, tp, value, traceback): + # Restore pyenv ENV vars + for i in range(len(self.env_pyenv_keys)): + if self.env_pyenv_old_vals[i]: + os.putenv(self.env_pyenv_keys[i], + self.env_pyenv_old_vals[i]) + + with enter_pyenv_shell_env(): + pyenv_virtualenv_path = subprocess.check_output( + ['pyenv', 'prefix'], + cwd=self._extra_sys_path[0], + encoding='utf8').strip() + for p in jedi.api.environment.create_environment( + pyenv_virtualenv_path, safe=False).get_sys_path(): + sys_paths.add(p) + + for p in jedi.api.environment.get_cached_default_environment( + ).get_sys_path(): + if p not in sys_paths: + sys_paths.add(p) + + path.extend(sys_paths) return path From e3ff7391133b490def8da9db24ea44447e37658f Mon Sep 17 00:00:00 2001 From: Sinkerine Date: Sun, 22 Sep 2019 10:07:22 -0700 Subject: [PATCH 2/2] Minor fixed indicated by lint --- pyls/workspace.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pyls/workspace.py b/pyls/workspace.py index 29c6dac1..fccfe7c1 100644 --- a/pyls/workspace.py +++ b/pyls/workspace.py @@ -222,11 +222,9 @@ def sys_path(self): sys_paths = set() # TODO(gatesn): #339 - make better use of jedi environments, they seem pretty powerful # Support pyenv virtualenv for LSP project roots - if distutils.spawn.find_executable( - 'pyenv') and self._extra_sys_path and len( - self._extra_sys_path) > 0: + if distutils.spawn.find_executable('pyenv') and self._extra_sys_path: - class enter_pyenv_shell_env(): + class enter_pyenv_shell_env(object): def __init__(self): self.env_pyenv_keys = ['PYENV_VERSION', 'PYENV_DIR'] self.env_pyenv_old_vals = []