Skip to content

Commit

Permalink
Merge pull request #5533 from pypa/issue-2538-venv-creator
Browse files Browse the repository at this point in the history
Refactor virtualenv create logic and add retry if creator venv results in error
  • Loading branch information
matteius committed Dec 17, 2022
2 parents 7322935 + b717a7a commit fe43762
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 28 deletions.
4 changes: 3 additions & 1 deletion news/5477.bugfix.rst
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
Check if ``venv`` module is available and fallback to prior logic when it is not.
virtualenv creation no longer uses ``--creator=venv`` by default; introduced two environment variables:
``PIPENV_VIRTUALENV_CREATOR`` -- May be specified to instruct virtualenv which ``--creator=`` to use.
``PIPENV_VIRTUALENV_COPIES`` -- When specified as truthy, instructs virtualenv to not use symlinks.
49 changes: 22 additions & 27 deletions pipenv/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -961,6 +961,27 @@ def convert_three_to_python(three, python):
return python


def _create_virtualenv_cmd(project, python, site_packages=False):
cmd = [
Path(sys.executable).absolute().as_posix(),
"-m",
"virtualenv",
]
if project.s.PIPENV_VIRTUALENV_CREATOR:
cmd.append(f"--creator={project.s.PIPENV_VIRTUALENV_CREATOR}")
cmd.append(f"--prompt={project.name}")
cmd.append(f"--python={python}")
cmd.append(project.get_location_for_virtualenv())
if project.s.PIPENV_VIRTUALENV_COPIES:
cmd.append("--copies")

# Pass site-packages flag to virtualenv, if desired...
if site_packages:
cmd.append("--system-site-packages")

return cmd


def do_create_virtualenv(project, python=None, site_packages=None, pypi_mirror=None):
"""Creates a virtualenv."""

Expand Down Expand Up @@ -989,46 +1010,22 @@ def do_create_virtualenv(project, python=None, site_packages=None, pypi_mirror=N
err=True,
)

try:
import venv # noqa

cmd = [
Path(sys.executable).absolute().as_posix(),
"-m",
"virtualenv",
"--creator=venv",
f"--prompt={project.name}",
f"--python={python}",
project.get_location_for_virtualenv(),
]
except ImportError:
cmd = [
Path(sys.executable).absolute().as_posix(),
"-m",
"virtualenv",
f"--prompt={project.name}",
f"--python={python}",
project.get_location_for_virtualenv(),
]

# Pass site-packages flag to virtualenv, if desired...
if site_packages:
click.echo(
click.style(fix_utf8("Making site-packages available..."), bold=True),
err=True,
)
cmd.append("--system-site-packages")

if pypi_mirror:
pip_config = {"PIP_INDEX_URL": pypi_mirror}
else:
pip_config = {}

# Actually create the virtualenv.
error = None
with console.status(
"Creating virtual environment...", spinner=project.s.PIPENV_SPINNER
):
cmd = _create_virtualenv_cmd(project, python, site_packages=site_packages)
c = subprocess_run(cmd, env=pip_config)
click.secho(f"{c.stdout}", fg="cyan", err=True)
if c.returncode != 0:
Expand All @@ -1052,7 +1049,6 @@ def do_create_virtualenv(project, python=None, site_packages=None, pypi_mirror=N
)

# Associate project directory with the environment.
# This mimics Pew's "setproject".
project_file_name = os.path.join(project.virtualenv_location, ".project")
with open(project_file_name, "w") as f:
f.write(project.project_directory)
Expand All @@ -1068,7 +1064,6 @@ def do_create_virtualenv(project, python=None, site_packages=None, pypi_mirror=N
pipfile=project.parsed_pipfile,
project=project,
)
project._environment.add_dist("pipenv")
# Say where the virtualenv is.
do_where(project, virtualenv=True, bare=False)

Expand Down
10 changes: 10 additions & 0 deletions pipenv/environments.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,16 @@ def __init__(self) -> None:
)
"""Tells Pipenv whether to name the venv something other than the default dir name."""

self.PIPENV_VIRTUALENV_CREATOR = get_from_env(
"VIRTUALENV_CREATOR", check_for_negation=False
)
"""Tells Pipenv to use the virtualenv --creator= argument with the user specified value."""

self.PIPENV_VIRTUALENV_COPIES = get_from_env(
"VIRTUALENV_COPIES", check_for_negation=True
)
"""Tells Pipenv to use the virtualenv --copies to prevent symlinks when specified as Truthy."""

self.PIPENV_PYUP_API_KEY = get_from_env("PYUP_API_KEY", check_for_negation=False)

# Internal, support running in a different Python from sys.executable.
Expand Down

0 comments on commit fe43762

Please sign in to comment.