diff --git a/pipenv/project.py b/pipenv/project.py index c5f451e4..751b9c5b 100644 --- a/pipenv/project.py +++ b/pipenv/project.py @@ -267,7 +267,18 @@ class Project(object): def get_location_for_virtualenv(self): if self.is_venv_in_project(): return os.path.join(self.project_directory, ".venv") - return str(get_workon_home().joinpath(self.virtualenv_name)) + + name = self.virtualenv_name + if self.project_directory: + venv_path = os.path.join(self.project_directory, ".venv") + if os.path.isfile(venv_path): + with open(venv_path, "r") as f: + name = f.read() + # Assume file's contents is a path if it contains slashes. + if '/' in name or '\\' in name: + return name + + return str(get_workon_home().joinpath(name)) def get_installed_packages(self): from . import PIPENV_ROOT, PIPENV_VENDOR, PIPENV_PATCHED diff --git a/tests/integration/test_dot_venv.py b/tests/integration/test_dot_venv.py index e7b157f3..6a8bedd9 100644 --- a/tests/integration/test_dot_venv.py +++ b/tests/integration/test_dot_venv.py @@ -1,5 +1,6 @@ import os +from pipenv._compat import TemporaryDirectory, Path from pipenv.project import Project from pipenv.utils import temp_environ, normalize_drive, get_windows_path from pipenv.vendor import delegator @@ -39,3 +40,53 @@ def test_reuse_previous_venv(PipenvInstance, pypi): c = p.pipenv('install requests') assert c.return_code == 0 assert normalize_drive(p.path) in p.pipenv('--venv').out + +@pytest.mark.dotvenv +def test_venv_file_with_name(PipenvInstance, pypi): + with PipenvInstance(chdir=True, pypi=pypi) as p: + file_path = os.path.join(p.path, ".venv") + venv_name = "test-project" + with open(file_path, "w") as f: + f.write(venv_name) + + with temp_environ(), TemporaryDirectory( + prefix="pipenv-", suffix="temp_workon_home" + ) as workon_home: + os.environ["WORKON_HOME"] = workon_home.name + if "PIPENV_VENV_IN_PROJECT" in os.environ: + del os.environ["PIPENV_VENV_IN_PROJECT"] + + c = p.pipenv("install requests") + assert c.return_code == 0 + + venv_loc = None + for line in c.err.splitlines(): + if line.startswith("Virtualenv location:"): + venv_loc = Path(line.split(":", 1)[-1].strip()) + assert venv_loc is not None + assert venv_loc.joinpath(".project").exists() + assert Path(venv_loc.name) == Path(venv_name) + +@pytest.mark.dotvenv +def test_venv_file_with_path(PipenvInstance, pypi): + with temp_environ(), PipenvInstance(chdir=True, pypi=pypi) as p: + with TemporaryDirectory( + prefix='pipenv-', suffix="-test_venv" + ) as venv_path: + if "PIPENV_VENV_IN_PROJECT" in os.environ: + del os.environ["PIPENV_VENV_IN_PROJECT"] + + file_path = os.path.join(p.path, ".venv") + with open(file_path, "w") as f: + f.write(venv_path.name) + + c = p.pipenv("install requests") + assert c.return_code == 0 + + venv_loc = None + for line in c.err.splitlines(): + if line.startswith("Virtualenv location:"): + venv_loc = Path(line.split(":", 1)[-1].strip()) + assert venv_loc is not None + assert venv_loc.joinpath(".project").exists() + assert venv_loc == Path(venv_path.name)