From d62490faaa432344bd33c7c282b47a45373c48dd Mon Sep 17 00:00:00 2001 From: Ryan Clary Date: Sat, 20 Jun 2020 16:50:44 -0700 Subject: [PATCH 1/4] * Allow explicit environment variables passed to jedi environment (see davidhalter/jedi#1617 and davidhalter/jedi#1619) * Requires jedi>=0.17.2 --- pyls/workspace.py | 17 +++++++++++------ vscode-client/package.json | 5 +++++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/pyls/workspace.py b/pyls/workspace.py index 7d5b95eb..cfeb0645 100644 --- a/pyls/workspace.py +++ b/pyls/workspace.py @@ -226,14 +226,16 @@ def jedi_names(self, all_scopes=False, definitions=True, references=False): def jedi_script(self, position=None): extra_paths = [] environment_path = None + env_vars = {} if self._config: jedi_settings = self._config.plugin_settings('jedi', document_path=self.path) environment_path = jedi_settings.get('environment') extra_paths = jedi_settings.get('extra_paths') or [] + env_vars = jedi_settings.get('env_vars') or {} - environment = self.get_enviroment(environment_path) if environment_path else None - sys_path = self.sys_path(environment_path) + extra_paths + environment = self.get_enviroment(environment_path, env_vars=env_vars) if environment_path else None + sys_path = self.sys_path(environment_path, env_vars=env_vars) + extra_paths project_path = self._workspace.root_path kwargs = { @@ -249,7 +251,8 @@ def jedi_script(self, position=None): return jedi.Script(**kwargs) - def get_enviroment(self, environment_path=None): + def get_enviroment(self, environment_path=None, **kwargs): + # TODO: when safe to break API, use env_vars explicitly to pass to create_environment # TODO(gatesn): #339 - make better use of jedi environments, they seem pretty powerful if environment_path is None: environment = jedi.api.environment.get_cached_default_environment() @@ -257,14 +260,16 @@ def get_enviroment(self, environment_path=None): if environment_path in self._workspace._environments: environment = self._workspace._environments[environment_path] else: - environment = jedi.api.environment.create_environment(path=environment_path, safe=False) + environment = jedi.api.environment.create_environment(path=environment_path, + safe=False, **kwargs) self._workspace._environments[environment_path] = environment return environment - def sys_path(self, environment_path=None): + def sys_path(self, environment_path=None, **kwargs): # Copy our extra sys path + # TODO: when safe to break API, use env_vars explicitly to pass to create_environment path = list(self._extra_sys_path) - environment = self.get_enviroment(environment_path=environment_path) + environment = self.get_enviroment(environment_path=environment_path, **kwargs) path.extend(environment.get_sys_path()) return path diff --git a/vscode-client/package.json b/vscode-client/package.json index 0cca6a32..58a8c3d9 100644 --- a/vscode-client/package.json +++ b/vscode-client/package.json @@ -40,6 +40,11 @@ "default": [], "description": "Define extra paths for jedi.Script." }, + "pyls.plugins.jedi.env_vars": { + "type": "dictionary", + "default": {}, + "description": "Define environment variables for jedi.Script and Jedi.names." + }, "pyls.plugins.jedi.environment": { "type": "string", "default": null, From 62177b0b38e84c123de13c0a38f264a209c2228a Mon Sep 17 00:00:00 2001 From: Ryan Clary Date: Wed, 22 Jul 2020 11:19:29 -0700 Subject: [PATCH 2/4] * make default env_vars=None; this maintains Popen default behavior --- pyls/workspace.py | 4 ++-- vscode-client/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyls/workspace.py b/pyls/workspace.py index cfeb0645..1db0ca5d 100644 --- a/pyls/workspace.py +++ b/pyls/workspace.py @@ -226,13 +226,13 @@ def jedi_names(self, all_scopes=False, definitions=True, references=False): def jedi_script(self, position=None): extra_paths = [] environment_path = None - env_vars = {} + env_vars = None if self._config: jedi_settings = self._config.plugin_settings('jedi', document_path=self.path) environment_path = jedi_settings.get('environment') extra_paths = jedi_settings.get('extra_paths') or [] - env_vars = jedi_settings.get('env_vars') or {} + env_vars = jedi_settings.get('env_vars') environment = self.get_enviroment(environment_path, env_vars=env_vars) if environment_path else None sys_path = self.sys_path(environment_path, env_vars=env_vars) + extra_paths diff --git a/vscode-client/package.json b/vscode-client/package.json index 58a8c3d9..f28437ca 100644 --- a/vscode-client/package.json +++ b/vscode-client/package.json @@ -42,7 +42,7 @@ }, "pyls.plugins.jedi.env_vars": { "type": "dictionary", - "default": {}, + "default": null, "description": "Define environment variables for jedi.Script and Jedi.names." }, "pyls.plugins.jedi.environment": { From d1956577acd31441c7b6adaee57a5f0512e4ddb5 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Sat, 26 Sep 2020 14:05:51 -0500 Subject: [PATCH 3/4] Drop PYTHONPATH before creating a Jedi environment That avoids an error in Jedi --- pyls/workspace.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pyls/workspace.py b/pyls/workspace.py index 1db0ca5d..4f97641e 100644 --- a/pyls/workspace.py +++ b/pyls/workspace.py @@ -234,6 +234,12 @@ def jedi_script(self, position=None): extra_paths = jedi_settings.get('extra_paths') or [] env_vars = jedi_settings.get('env_vars') + # Drop PYTHONPATH from env_vars before creating the environment because that makes + # Jedi throw an error. + if env_vars is None: + env_vars = os.environ.copy() + env_vars.pop('PYTHONPATH', None) + environment = self.get_enviroment(environment_path, env_vars=env_vars) if environment_path else None sys_path = self.sys_path(environment_path, env_vars=env_vars) + extra_paths project_path = self._workspace.root_path From ab97333156f095a179cfde5a027e0bab50eb904b Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Sat, 26 Sep 2020 14:09:37 -0500 Subject: [PATCH 4/4] Increase Jedi minimal required version to be able to use env_vars in create_environment --- pyls/workspace.py | 10 +++++----- setup.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pyls/workspace.py b/pyls/workspace.py index 4f97641e..31262442 100644 --- a/pyls/workspace.py +++ b/pyls/workspace.py @@ -257,8 +257,7 @@ def jedi_script(self, position=None): return jedi.Script(**kwargs) - def get_enviroment(self, environment_path=None, **kwargs): - # TODO: when safe to break API, use env_vars explicitly to pass to create_environment + def get_enviroment(self, environment_path=None, env_vars=None): # TODO(gatesn): #339 - make better use of jedi environments, they seem pretty powerful if environment_path is None: environment = jedi.api.environment.get_cached_default_environment() @@ -267,15 +266,16 @@ def get_enviroment(self, environment_path=None, **kwargs): environment = self._workspace._environments[environment_path] else: environment = jedi.api.environment.create_environment(path=environment_path, - safe=False, **kwargs) + safe=False, + env_vars=env_vars) self._workspace._environments[environment_path] = environment return environment - def sys_path(self, environment_path=None, **kwargs): + def sys_path(self, environment_path=None, env_vars=None): # Copy our extra sys path # TODO: when safe to break API, use env_vars explicitly to pass to create_environment path = list(self._extra_sys_path) - environment = self.get_enviroment(environment_path=environment_path, **kwargs) + environment = self.get_enviroment(environment_path=environment_path, env_vars=env_vars) path.extend(environment.get_sys_path()) return path diff --git a/setup.py b/setup.py index a050ff21..12782990 100755 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ 'configparser; python_version<"3.0"', 'future>=0.14.0; python_version<"3"', 'backports.functools_lru_cache; python_version<"3.2"', - 'jedi>=0.17.0,<0.18.0', + 'jedi>=0.17.2,<0.18.0', 'python-jsonrpc-server>=0.4.0', 'pluggy', 'ujson<=2.0.3 ; platform_system!="Windows" and python_version<"3.0"',