From 6d0f0a9f90b76f6f1306dd02a717e0bd3fc50548 Mon Sep 17 00:00:00 2001 From: Arun Babu Neelicattu Date: Tue, 20 Oct 2020 13:07:57 +0200 Subject: [PATCH] env: do not modify os.environ Replace updates of os.environ with explcit passing of `env` to subprocess calls. Relates-to: #3199 --- poetry/utils/env.py | 49 ++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/poetry/utils/env.py b/poetry/utils/env.py index 9d660c709dd..681027ac3a4 100644 --- a/poetry/utils/env.py +++ b/poetry/utils/env.py @@ -10,6 +10,7 @@ import textwrap from contextlib import contextmanager +from copy import deepcopy from typing import Any from typing import Dict from typing import List @@ -1077,15 +1078,13 @@ def _run(self, cmd, **kwargs): def execute(self, bin, *args, **kwargs): bin = self._bin(bin) + env = kwargs.pop("env", {k: v for k, v in os.environ.items()}) if not self._is_windows: args = [bin] + list(args) - if "env" in kwargs: - return os.execvpe(bin, args, kwargs["env"]) - else: - return os.execvp(bin, args) + return os.execvpe(bin, args, env=env) else: - exe = subprocess.Popen([bin] + list(args), **kwargs) + exe = subprocess.Popen([bin] + list(args), env=env, **kwargs) exe.communicate() return exe.returncode @@ -1322,24 +1321,32 @@ def is_sane(self): return os.path.exists(self.python) and os.path.exists(self._bin("pip")) def _run(self, cmd, **kwargs): - with self.temp_environ(): - os.environ["PATH"] = self._updated_path() - os.environ["VIRTUAL_ENV"] = str(self._path) - - self.unset_env("PYTHONHOME") - self.unset_env("__PYVENV_LAUNCHER__") + kwargs["env"] = self.get_temp_environ(environ=kwargs.get("env")) + return super(VirtualEnv, self)._run(cmd, **kwargs) + + def get_temp_environ( + self, environ=None, exclude=None, **kwargs + ): # type: (Optional[Dict[str, str]], Optional[List[str]], **str) -> Dict[str, str] + exclude = exclude or [] + exclude.extend(["PYTHONHOME", "__PYVENV_LAUNCHER__"]) + + if environ: + environ = deepcopy(environ) + for key in exclude: + environ.pop(key, None) + else: + environ = {k: v for k, v in os.environ.items() if k not in exclude} - return super(VirtualEnv, self)._run(cmd, **kwargs) + environ.update(kwargs) - def execute(self, bin, *args, **kwargs): - with self.temp_environ(): - os.environ["PATH"] = self._updated_path() - os.environ["VIRTUAL_ENV"] = str(self._path) + environ["PATH"] = self._updated_path() + environ["VIRTUAL_ENV"] = str(self._path) - self.unset_env("PYTHONHOME") - self.unset_env("__PYVENV_LAUNCHER__") + return environ - return super(VirtualEnv, self).execute(bin, *args, **kwargs) + def execute(self, bin, *args, **kwargs): + kwargs["env"] = self.get_temp_environ(environ=kwargs.get("env")) + return super(VirtualEnv, self).execute(bin, *args, **kwargs) @contextmanager def temp_environ(self): @@ -1350,10 +1357,6 @@ def temp_environ(self): os.environ.clear() os.environ.update(environ) - def unset_env(self, key): - if key in os.environ: - del os.environ[key] - def _updated_path(self): return os.pathsep.join([str(self._bin_dir), os.environ.get("PATH", "")])