Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use existing .venv even without explicit in-project #7792

Merged
merged 4 commits into from
Apr 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 24 additions & 21 deletions src/poetry/utils/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,11 @@ def get_python_version(

return Version.parse(version)

@property
def in_project_venv(self) -> Path:
venv: Path = self._poetry.file.parent / ".venv"
return venv

def activate(self, python: str) -> Env:
venv_path = self._poetry.config.virtualenvs_path
cwd = self._poetry.file.parent
Expand Down Expand Up @@ -621,12 +626,11 @@ def activate(self, python: str) -> Env:
patch = python_version.text

create = False
is_root_venv = self._poetry.config.get("virtualenvs.in-project")
# If we are required to create the virtual environment in the root folder,
# If we are required to create the virtual environment in the project directory,
# create or recreate it if needed
if is_root_venv:
if self.use_in_project_venv():
create = False
venv = self._poetry.file.parent / ".venv"
venv = self.in_project_venv
if venv.exists():
# We need to check if the patch version is correct
_venv = VirtualEnv(venv)
Expand Down Expand Up @@ -730,12 +734,8 @@ def get(self, reload: bool = False) -> Env:

if not in_venv or env is not None:
# Checking if a local virtualenv exists
if (
self._poetry.config.get("virtualenvs.in-project") is not False
and (cwd / ".venv").exists()
and (cwd / ".venv").is_dir()
):
venv = cwd / ".venv"
if self.use_in_project_venv():
venv = self.in_project_venv

return VirtualEnv(venv)

Expand Down Expand Up @@ -772,12 +772,8 @@ def list(self, name: str | None = None) -> list[VirtualEnv]:
venv_path = self._poetry.config.virtualenvs_path
env_list = [VirtualEnv(p) for p in sorted(venv_path.glob(f"{venv_name}-py*"))]

venv = self._poetry.file.parent / ".venv"
if (
self._poetry.config.get("virtualenvs.in-project") is not False
and venv.exists()
and venv.is_dir()
):
if self.use_in_project_venv():
venv = self.in_project_venv
env_list.insert(0, VirtualEnv(venv))
return env_list

Expand Down Expand Up @@ -891,6 +887,12 @@ def remove(self, python: str) -> Env:

return VirtualEnv(venv_path, venv_path)

def use_in_project_venv(self) -> bool:
in_project: bool | None = self._poetry.config.get("virtualenvs.in-project")
if in_project is not None:
return in_project
return self.in_project_venv.is_dir()

def create_venv(
self,
name: str | None = None,
Expand Down Expand Up @@ -918,7 +920,7 @@ def create_venv(
return env

create_venv = self._poetry.config.get("virtualenvs.create")
root_venv = self._poetry.config.get("virtualenvs.in-project")
in_project_venv = self.use_in_project_venv()
prefer_active_python = self._poetry.config.get(
"virtualenvs.prefer-active-python"
)
Expand All @@ -927,12 +929,13 @@ def create_venv(
if not executable and prefer_active_python:
executable = self._detect_active_python()

venv_path: Path = (
cwd / ".venv" if root_venv else self._poetry.config.virtualenvs_path
venv_path = (
self.in_project_venv
if in_project_venv
else self._poetry.config.virtualenvs_path
)
if not name:
name = self._poetry.package.name
assert name is not None

python_patch = ".".join([str(v) for v in sys.version_info[:3]])
python_minor = ".".join([str(v) for v in sys.version_info[:2]])
Expand Down Expand Up @@ -1007,7 +1010,7 @@ def create_venv(
self._poetry.package.python_versions
)

if root_venv:
if in_project_venv:
venv = venv_path
else:
name = self.generate_env_name(name, str(cwd))
Expand Down
48 changes: 47 additions & 1 deletion tests/utils/test_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,52 @@ def check_output(cmd: list[str], *args: Any, **kwargs: Any) -> str:
return check_output


def test_activate_in_project_venv_no_explicit_config(
tmp_path: Path,
manager: EnvManager,
poetry: Poetry,
mocker: MockerFixture,
venv_name: str,
in_project_venv_dir: Path,
) -> None:
mocker.patch("shutil.which", side_effect=lambda py: f"/usr/bin/{py}")
mocker.patch(
"subprocess.check_output",
side_effect=check_output_wrapper(),
)
mocker.patch(
"subprocess.Popen.communicate",
side_effect=[
("/prefix", None),
('{"version_info": [3, 7, 0]}', None),
("/prefix", None),
("/prefix", None),
("/prefix", None),
],
)
m = mocker.patch("poetry.utils.env.EnvManager.build_venv", side_effect=build_venv)

env = manager.activate("python3.7")

assert env.path == tmp_path / "poetry-fixture-simple" / ".venv"
assert env.base == Path("/prefix")

m.assert_called_with(
tmp_path / "poetry-fixture-simple" / ".venv",
executable=Path("/usr/bin/python3.7"),
flags={
"always-copy": False,
"system-site-packages": False,
"no-pip": False,
"no-setuptools": False,
},
prompt="simple-project-py3.7",
)

envs_file = TOMLFile(tmp_path / "envs.toml")
assert not envs_file.exists()


def test_activate_activates_non_existing_virtualenv_no_envs_file(
tmp_path: Path,
manager: EnvManager,
Expand Down Expand Up @@ -1382,7 +1428,7 @@ def test_activate_with_in_project_setting_does_not_fail_if_no_venvs_dir(
)
mocker.patch(
"subprocess.Popen.communicate",
side_effect=[("/prefix", None), ("/prefix", None)],
side_effect=[("/prefix", None), ("/prefix", None), ("/prefix", None)],
)
m = mocker.patch("poetry.utils.env.EnvManager.build_venv")

Expand Down