Skip to content

Commit 15d7a26

Browse files
committed
env: do not modify os.environ
Replace updates of os.environ with explcit passing of `env` to subprocess calls. Relates-to: #3199
1 parent 8c5611c commit 15d7a26

File tree

1 file changed

+28
-22
lines changed

1 file changed

+28
-22
lines changed

poetry/utils/env.py

+28-22
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import textwrap
1212

1313
from contextlib import contextmanager
14+
from copy import deepcopy
1415
from pathlib import Path
1516
from subprocess import CalledProcessError
1617
from typing import Any
@@ -1143,15 +1144,13 @@ def execute(self, bin: str, *args: str, **kwargs: Any) -> Optional[int]:
11431144
return self.run_pip(*args, **kwargs)
11441145

11451146
bin = self._bin(bin)
1147+
env = kwargs.pop("env", {k: v for k, v in os.environ.items()})
11461148

11471149
if not self._is_windows:
11481150
args = [bin] + list(args)
1149-
if "env" in kwargs:
1150-
return os.execvpe(bin, args, kwargs["env"])
1151-
else:
1152-
return os.execvp(bin, args)
1151+
return os.execvpe(bin, args, env=env)
11531152
else:
1154-
exe = subprocess.Popen([bin] + list(args), **kwargs)
1153+
exe = subprocess.Popen([bin] + list(args), env=env, **kwargs)
11551154
exe.communicate()
11561155
return exe.returncode
11571156

@@ -1388,24 +1387,35 @@ def is_sane(self) -> bool:
13881387
return os.path.exists(self.python)
13891388

13901389
def _run(self, cmd: List[str], **kwargs: Any) -> Optional[int]:
1391-
with self.temp_environ():
1392-
os.environ["PATH"] = self._updated_path()
1393-
os.environ["VIRTUAL_ENV"] = str(self._path)
1390+
kwargs["env"] = self.get_temp_environ(environ=kwargs.get("env"))
1391+
return super(VirtualEnv, self)._run(cmd, **kwargs)
13941392

1395-
self.unset_env("PYTHONHOME")
1396-
self.unset_env("__PYVENV_LAUNCHER__")
1393+
def get_temp_environ(
1394+
self,
1395+
environ: Optional[Dict[str, str]] = None,
1396+
exclude: Optional[List[str]] = None,
1397+
**kwargs: str,
1398+
) -> Dict[str, str]:
1399+
exclude = exclude or []
1400+
exclude.extend(["PYTHONHOME", "__PYVENV_LAUNCHER__"])
1401+
1402+
if environ:
1403+
environ = deepcopy(environ)
1404+
for key in exclude:
1405+
environ.pop(key, None)
1406+
else:
1407+
environ = {k: v for k, v in os.environ.items() if k not in exclude}
13971408

1398-
return super(VirtualEnv, self)._run(cmd, **kwargs)
1409+
environ.update(kwargs)
13991410

1400-
def execute(self, bin: str, *args: str, **kwargs: Any) -> Optional[int]:
1401-
with self.temp_environ():
1402-
os.environ["PATH"] = self._updated_path()
1403-
os.environ["VIRTUAL_ENV"] = str(self._path)
1411+
environ["PATH"] = self._updated_path()
1412+
environ["VIRTUAL_ENV"] = str(self._path)
14041413

1405-
self.unset_env("PYTHONHOME")
1406-
self.unset_env("__PYVENV_LAUNCHER__")
1414+
return environ
14071415

1408-
return super(VirtualEnv, self).execute(bin, *args, **kwargs)
1416+
def execute(self, bin: str, *args: str, **kwargs: Any) -> Optional[int]:
1417+
kwargs["env"] = self.get_temp_environ(environ=kwargs.get("env"))
1418+
return super(VirtualEnv, self).execute(bin, *args, **kwargs)
14091419

14101420
@contextmanager
14111421
def temp_environ(self) -> Iterator[None]:
@@ -1416,10 +1426,6 @@ def temp_environ(self) -> Iterator[None]:
14161426
os.environ.clear()
14171427
os.environ.update(environ)
14181428

1419-
def unset_env(self, key: str) -> None:
1420-
if key in os.environ:
1421-
del os.environ[key]
1422-
14231429
def _updated_path(self) -> str:
14241430
return os.pathsep.join([str(self._bin_dir), os.environ.get("PATH", "")])
14251431

0 commit comments

Comments
 (0)