Skip to content

Commit

Permalink
env: do not modify os.environ
Browse files Browse the repository at this point in the history
Replace updates of os.environ with explcit passing of `env` to
subprocess calls.

Relates-to: python-poetry#3199
  • Loading branch information
abn committed Mar 27, 2021
1 parent 8c5611c commit 78eaf05
Showing 1 changed file with 28 additions and 22 deletions.
50 changes: 28 additions & 22 deletions poetry/utils/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import textwrap

from contextlib import contextmanager
from copy import deepcopy
from pathlib import Path
from subprocess import CalledProcessError
from typing import Any
Expand Down Expand Up @@ -1143,15 +1144,13 @@ def execute(self, bin: str, *args: str, **kwargs: Any) -> Optional[int]:
return self.run_pip(*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

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

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

self.unset_env("PYTHONHOME")
self.unset_env("__PYVENV_LAUNCHER__")
def get_temp_environ(
self,
environ: Optional[Dict[str, str]] = None,
exclude: Optional[List[str]] = None,
**kwargs: 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: str, *args: str, **kwargs: Any) -> Optional[int]:
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: str, *args: str, **kwargs: Any) -> Optional[int]:
kwargs["env"] = self.get_temp_environ(environ=kwargs.get("env"))
return super(VirtualEnv, self).execute(bin, *args, **kwargs)

@contextmanager
def temp_environ(self) -> Iterator[None]:
Expand All @@ -1416,10 +1426,6 @@ def temp_environ(self) -> Iterator[None]:
os.environ.clear()
os.environ.update(environ)

def unset_env(self, key: str) -> None:
if key in os.environ:
del os.environ[key]

def _updated_path(self) -> str:
return os.pathsep.join([str(self._bin_dir), os.environ.get("PATH", "")])

Expand Down

0 comments on commit 78eaf05

Please sign in to comment.