Skip to content

Commit

Permalink
installer: support for unnormalized dist-info
Browse files Browse the repository at this point in the history
  • Loading branch information
radoering committed Mar 17, 2023
1 parent 40061f9 commit e4dfeda
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 21 deletions.
34 changes: 33 additions & 1 deletion src/poetry/installation/wheel_installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from installer import install
from installer.destinations import SchemeDictionaryDestination
from installer.sources import WheelFile
from packaging.utils import canonicalize_name

from poetry.__version__ import __version__
from poetry.utils._compat import WINDOWS
Expand All @@ -25,6 +26,37 @@
from poetry.utils.env import Env


class PatchedWheelFile(WheelFile):
# TODO: Patch from https://github.com/pypa/installer/issues/134
# can be removed if new installer release is available
@property
def dist_info_dir(self) -> str:
"""Name of the dist-info directory."""
if not hasattr(self, "_dist_info_dir"):
top_level_directories = {
path.split("/", 1)[0] for path in self._zipfile.namelist()
}
dist_infos = [
name for name in top_level_directories if name.endswith(".dist-info")
]

assert (
len(dist_infos) == 1
), "Wheel doesn't contain exactly one .dist-info directory"
dist_info_dir = dist_infos[0]

# NAME-VER.dist-info
di_dname = dist_info_dir.rsplit("-", 2)[0]
norm_di_dname = canonicalize_name(di_dname)
norm_file_dname = canonicalize_name(self.distribution)
assert (
norm_di_dname == norm_file_dname
), "Wheel .dist-info directory doesn't match wheel filename"

self._dist_info_dir = dist_info_dir
return self._dist_info_dir


class WheelDestination(SchemeDictionaryDestination):
""" """

Expand Down Expand Up @@ -97,7 +129,7 @@ def enable_bytecode_compilation(self, enable: bool = True) -> None:
self._destination.bytecode_optimization_levels = (1,) if enable else ()

def install(self, wheel: Path) -> None:
with WheelFile.open(Path(wheel.as_posix())) as source:
with PatchedWheelFile.open(Path(wheel.as_posix())) as source:
install(
source=source,
destination=self._destination.for_source(source),
Expand Down
Binary file not shown.
44 changes: 24 additions & 20 deletions tests/installation/test_chef.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import os
import shutil
import tempfile

from pathlib import Path
Expand All @@ -24,6 +25,7 @@
from pytest_mock import MockerFixture

from tests.conftest import Config
from tests.types import FixtureDirGetter


@pytest.fixture()
Expand Down Expand Up @@ -145,7 +147,9 @@ def test_get_found_cached_archive_for_link(
assert Path(cached) == archive


def test_get_cached_archives_for_link(config: Config, mocker: MockerFixture):
def test_get_cached_archives_for_link(
config: Config, mocker: MockerFixture, fixture_dir: FixtureDirGetter, tmp_path: Path
) -> None:
chef = Chef(
config,
MockEnv(
Expand All @@ -154,19 +158,21 @@ def test_get_cached_archives_for_link(config: Config, mocker: MockerFixture):
Factory.create_pool(config),
)

distributions = Path(__file__).parent.parent.joinpath("fixtures/distributions")
for file in fixture_dir("distributions").glob("demo-0.1.*"):
shutil.copy(file, tmp_path)
(Path(tmp_path) / "no-distribution-by-suffix.txt").touch()
mocker.patch.object(
chef,
"get_cache_directory_for_link",
return_value=distributions,
return_value=tmp_path,
)

archives = chef.get_cached_archives_for_link(
Link("https://files.python-poetry.org/demo-0.1.0.tar.gz")
)

assert archives
assert set(archives) == set(distributions.glob("demo-0.1.*"))
assert set(archives) == set(tmp_path.glob("demo-0.1.*"))


def test_get_cache_directory_for_link(config: Config, config_cache_dir: Path):
Expand All @@ -190,14 +196,12 @@ def test_get_cache_directory_for_link(config: Config, config_cache_dir: Path):
assert directory == expected


def test_prepare_sdist(config: Config, config_cache_dir: Path) -> None:
def test_prepare_sdist(
config: Config, config_cache_dir: Path, fixture_dir: FixtureDirGetter
) -> None:
chef = Chef(config, EnvManager.get_system_env(), Factory.create_pool(config))

archive = (
Path(__file__)
.parent.parent.joinpath("fixtures/distributions/demo-0.1.0.tar.gz")
.resolve()
)
archive = fixture_dir("distributions/demo-0.1.0.tar.gz").resolve()

destination = chef.get_cache_directory_for_link(Link(archive.as_uri()))

Expand All @@ -207,10 +211,12 @@ def test_prepare_sdist(config: Config, config_cache_dir: Path) -> None:
assert wheel.name == "demo-0.1.0-py3-none-any.whl"


def test_prepare_directory(config: Config, config_cache_dir: Path):
def test_prepare_directory(
config: Config, config_cache_dir: Path, fixture_dir: FixtureDirGetter
) -> None:
chef = Chef(config, EnvManager.get_system_env(), Factory.create_pool(config))

archive = Path(__file__).parent.parent.joinpath("fixtures/simple_project").resolve()
archive = fixture_dir("simple_project").resolve()

wheel = chef.prepare(archive)

Expand All @@ -222,16 +228,12 @@ def test_prepare_directory(config: Config, config_cache_dir: Path):


def test_prepare_directory_with_extensions(
config: Config, config_cache_dir: Path
config: Config, config_cache_dir: Path, fixture_dir: FixtureDirGetter
) -> None:
env = EnvManager.get_system_env()
chef = Chef(config, env, Factory.create_pool(config))

archive = (
Path(__file__)
.parent.parent.joinpath("fixtures/extended_with_no_setup")
.resolve()
)
archive = fixture_dir("extended_with_no_setup").resolve()

wheel = chef.prepare(archive)

Expand All @@ -242,10 +244,12 @@ def test_prepare_directory_with_extensions(
os.unlink(wheel)


def test_prepare_directory_editable(config: Config, config_cache_dir: Path):
def test_prepare_directory_editable(
config: Config, config_cache_dir: Path, fixture_dir: FixtureDirGetter
) -> None:
chef = Chef(config, EnvManager.get_system_env(), Factory.create_pool(config))

archive = Path(__file__).parent.parent.joinpath("fixtures/simple_project").resolve()
archive = fixture_dir("simple_project").resolve()

wheel = chef.prepare(archive, editable=True)

Expand Down
17 changes: 17 additions & 0 deletions tests/installation/test_wheel_installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,20 @@ def test_enable_bytecode_compilation(
assert list(cache_dir.glob("*.pyc"))
else:
assert not cache_dir.exists()


def test_install_wheel_with_unnormalized_dist_info(
fixture_dir: FixtureDirGetter, tmp_path: Path
) -> None:
wheel = fixture_dir("distributions/un_normalized_dist_info-0.1.0-py3-none-any.whl")
env = MockEnv(path=tmp_path)
installer = WheelInstaller(env)
installer.install(wheel)
dist_info_dir = (
Path(env.paths["purelib"]) / "Un.normalized_dist-info-0.1.0.dist-info"
)
assert dist_info_dir.exists()
assert (dist_info_dir / "INSTALLER").exists()
assert (dist_info_dir / "METADATA").exists()
assert (dist_info_dir / "RECORD").exists()
assert (dist_info_dir / "WHEEL").exists()

0 comments on commit e4dfeda

Please sign in to comment.