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

fix: Broken cache on Windows #4531

Merged
merged 8 commits into from
Nov 12, 2021
14 changes: 9 additions & 5 deletions poetry/installation/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from poetry.core.packages.file_dependency import FileDependency
from poetry.core.packages.package import Package
from poetry.core.packages.utils.link import Link
from poetry.core.packages.utils.utils import url_to_path
from poetry.core.pyproject.toml import PyProjectTOML
from poetry.utils._compat import decode
from poetry.utils.env import EnvCommandError
Expand Down Expand Up @@ -119,7 +120,7 @@ def verbose(self, verbose: bool = True) -> "Executor":
return self

def pip_install(
self, req: Union[Path, str], upgrade: bool = False, editable: bool = False
self, req: Union[Path, Link], upgrade: bool = False, editable: bool = False
) -> int:
func = pip_install
if editable:
Expand Down Expand Up @@ -504,7 +505,7 @@ def _install(self, operation: Union[Install, Update]) -> int:
)
)
self._write(operation, message)
return self.pip_install(str(archive), upgrade=operation.job_type == "update")
return self.pip_install(archive, upgrade=operation.job_type == "update")

def _update(self, operation: Union[Install, Update]) -> int:
return self._install(operation)
Expand Down Expand Up @@ -678,17 +679,20 @@ def _download_link(self, operation: Union[Install, Update], link: Link) -> Link:
return archive

@staticmethod
def _validate_archive_hash(archive: Path, package: Package) -> str:
def _validate_archive_hash(archive: Union[Path, Link], package: Package) -> str:
archive_path = (
url_to_path(archive.url) if isinstance(archive, Link) else archive
)
file_dep = FileDependency(
package.name,
Path(archive.path) if isinstance(archive, Link) else archive,
archive_path,
)
archive_hash = "sha256:" + file_dep.hash()
known_hashes = {f["hash"] for f in package.files}

if archive_hash not in known_hashes:
raise RuntimeError(
f"Hash for {package} from archive {archive.name} not found in known hashes (was: {archive_hash})"
f"Hash for {package} from archive {archive_path.name} not found in known hashes (was: {archive_hash})"
)

return archive_hash
Expand Down
10 changes: 7 additions & 3 deletions poetry/utils/pip.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,22 @@
from pathlib import Path
from typing import Union

from poetry.core.packages.utils.link import Link
from poetry.core.packages.utils.utils import url_to_path
from poetry.exceptions import PoetryException
from poetry.utils.env import Env
from poetry.utils.env import EnvCommandError
from poetry.utils.env import ephemeral_environment


def pip_install(
path: Union[Path, str],
path: Union[Path, Link],
neersighted marked this conversation as resolved.
Show resolved Hide resolved
environment: Env,
editable: bool = False,
deps: bool = False,
upgrade: bool = False,
) -> Union[int, str]:
path = Path(path) if isinstance(path, str) else path
path = url_to_path(path.url) if isinstance(path, Link) else path
is_wheel = path.suffix == ".whl"

# We disable version check here as we are already pinning to version available in either the
Expand Down Expand Up @@ -60,7 +62,9 @@ def pip_install(
raise PoetryException(f"Failed to install {path.as_posix()}") from e


def pip_editable_install(directory: Path, environment: Env) -> Union[int, str]:
def pip_editable_install(
directory: Union[Path, Link], environment: Env
) -> Union[int, str]:
return pip_install(
path=directory, environment=environment, editable=True, deps=False, upgrade=True
)
32 changes: 32 additions & 0 deletions tests/installation/test_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from poetry.config.config import Config
from poetry.core.packages.package import Package
from poetry.core.packages.utils.link import Link
from poetry.core.utils._compat import PY36
from poetry.installation.executor import Executor
from poetry.installation.operations import Install
Expand Down Expand Up @@ -462,3 +463,34 @@ def test_executor_should_write_pep610_url_references_for_git(
"url": package.source_url,
},
)


def test_executor_should_use_cached_link_and_hash(
tmp_venv, pool, config, io, mocker, fixture_dir
):
# Produce a file:/// URI that is a valid link
link_cached = Link(
fixture_dir("distributions")
.joinpath("demo-0.1.0-py2.py3-none-any.whl")
.as_uri()
)
mocker.patch(
"poetry.installation.chef.Chef.get_cached_archive_for_link",
return_value=link_cached,
)

package = Package("demo", "0.1.0")
# Set package.files so the executor will attempt to hash the package
package.files = [
{
"file": "demo-0.1.0-py2.py3-none-any.whl",
"hash": "sha256:70e704135718fffbcbf61ed1fc45933cfd86951a744b681000eaaa75da31f17a",
}
]

executor = Executor(tmp_venv, pool, config, io)
archive = executor._download_link(
Install(package),
Link("https://example.com/demo-0.1.0-py2.py3-none-any.whl"),
)
assert archive == link_cached
11 changes: 11 additions & 0 deletions tests/utils/test_pip.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import pytest

from poetry.core.packages.utils.link import Link
from poetry.core.packages.utils.utils import path_to_url
from poetry.utils.pip import pip_install


Expand All @@ -12,6 +14,15 @@ def test_pip_install_successful(tmp_dir, tmp_venv, fixture_dir):
assert "Successfully installed demo-0.1.0" in result


def test_pip_install_link(tmp_dir, tmp_venv, fixture_dir):
file_path = Link(
path_to_url(fixture_dir("distributions/demo-0.1.0-py2.py3-none-any.whl"))
)
result = pip_install(file_path, tmp_venv)

assert "Successfully installed demo-0.1.0" in result


def test_pip_install_with_keyboard_interrupt(tmp_dir, tmp_venv, fixture_dir, mocker):
file_path = fixture_dir("distributions/demo-0.1.0-py2.py3-none-any.whl")
mocker.patch("subprocess.run", side_effect=KeyboardInterrupt())
Expand Down