From 9449fb0f138ad8862ac5ff1ad38cd755287aee8d Mon Sep 17 00:00:00 2001 From: David Hotham Date: Sun, 25 Sep 2022 14:32:18 +0100 Subject: [PATCH] normalize source distribution names --- src/poetry/core/masonry/builders/sdist.py | 4 +- src/poetry/core/masonry/builders/wheel.py | 11 ++--- src/poetry/core/masonry/utils/helpers.py | 42 ++++++++++++++++++ ...2.3.tar.gz => simple_project-1.2.3.tar.gz} | Bin tests/integration/test_pep517.py | 2 +- tests/masonry/builders/test_complete.py | 10 ++--- tests/masonry/builders/test_sdist.py | 20 ++++----- tests/masonry/utils/test_helpers.py | 6 ++- 8 files changed, 72 insertions(+), 23 deletions(-) rename tests/fixtures/simple_project/dist/{simple-project-1.2.3.tar.gz => simple_project-1.2.3.tar.gz} (100%) diff --git a/src/poetry/core/masonry/builders/sdist.py b/src/poetry/core/masonry/builders/sdist.py index d853789ff..fca329d56 100644 --- a/src/poetry/core/masonry/builders/sdist.py +++ b/src/poetry/core/masonry/builders/sdist.py @@ -18,6 +18,7 @@ from poetry.core.masonry.builders.builder import Builder from poetry.core.masonry.builders.builder import BuildIncludeFile +from poetry.core.masonry.utils.helpers import distribution_name if TYPE_CHECKING: @@ -65,7 +66,8 @@ def build( if not target_dir.exists(): target_dir.mkdir(parents=True) - target = target_dir / f"{self._package.pretty_name}-{self._meta.version}.tar.gz" + name = distribution_name(self._package.name) + target = target_dir / f"{name}-{self._meta.version}.tar.gz" gz = GzipFile(target.as_posix(), mode="wb", mtime=0) tar = tarfile.TarFile( target.as_posix(), mode="w", fileobj=gz, format=tarfile.PAX_FORMAT diff --git a/src/poetry/core/masonry/builders/wheel.py b/src/poetry/core/masonry/builders/wheel.py index 17625a0ba..2909cff74 100644 --- a/src/poetry/core/masonry/builders/wheel.py +++ b/src/poetry/core/masonry/builders/wheel.py @@ -24,12 +24,14 @@ from poetry.core.constraints.version import parse_constraint from poetry.core.masonry.builders.builder import Builder from poetry.core.masonry.builders.sdist import SdistBuilder -from poetry.core.masonry.utils.helpers import escape_name +from poetry.core.masonry.utils.helpers import distribution_name from poetry.core.masonry.utils.helpers import normalize_file_permissions from poetry.core.masonry.utils.package_include import PackageInclude if TYPE_CHECKING: + from packaging.utils import NormalizedName + from poetry.core.poetry import Poetry wheel_file_template = """\ @@ -280,7 +282,7 @@ def wheel_data_folder(self) -> str: @property def wheel_filename(self) -> str: - name = escape_name(self._package.pretty_name) + name = distribution_name(self._package.name) version = self._meta.version return f"{name}-{version}-{self.tag}.whl" @@ -289,9 +291,8 @@ def supports_python2(self) -> bool: parse_constraint(">=2.0.0 <3.0.0") ) - def dist_info_name(self, distribution: str, version: str) -> str: - escaped_name = escape_name(distribution) - + def dist_info_name(self, name: NormalizedName, version: str) -> str: + escaped_name = distribution_name(name) return f"{escaped_name}-{version}.dist-info" @property diff --git a/src/poetry/core/masonry/utils/helpers.py b/src/poetry/core/masonry/utils/helpers.py index 7a3738c6a..a93212733 100644 --- a/src/poetry/core/masonry/utils/helpers.py +++ b/src/poetry/core/masonry/utils/helpers.py @@ -3,6 +3,17 @@ import re import warnings +from typing import TYPE_CHECKING +from typing import NewType +from typing import cast + + +if TYPE_CHECKING: + from packaging.utils import NormalizedName + + +DistributionName = NewType("DistributionName", str) + def normalize_file_permissions(st_mode: int) -> int: """ @@ -39,4 +50,35 @@ def escape_name(name: str) -> str: Escaped wheel name as specified in https://packaging.python.org/en/latest/specifications/binary-distribution-format/#escaping-and-unicode. This function should only be used for the generation of artifact names, and not to normalize or filter existing artifact names. """ + warnings.warn( + "escape_name() is deprecated. Use packaging.utils.canonicalize_name() and" + " distribution_name() instead.", + DeprecationWarning, + stacklevel=2, + ) return re.sub(r"[-_.]+", "_", name, flags=re.UNICODE).lower() + + +def distribution_name(name: NormalizedName) -> DistributionName: + """ + A normalized name, but with "-" replaced by "_". This is used in various places: + + https://packaging.python.org/en/latest/specifications/binary-distribution-format/#escaping-and-unicode + + In distribution names ... This is equivalent to PEP 503 normalisation followed by + replacing - with _. + + https://packaging.python.org/en/latest/specifications/source-distribution-format/#source-distribution-file-name + + ... {name} is normalised according to the same rules as for binary distributions + + https://packaging.python.org/en/latest/specifications/recording-installed-packages/#the-dist-info-directory + + This directory is named as {name}-{version}.dist-info, with name and version + fields corresponding to Core metadata specifications. Both fields must be + normalized (see PEP 503 and PEP 440 for the definition of normalization for each + field respectively), and replace dash (-) characters with underscore + (_) characters ... + """ + distribution_name = name.replace("-", "_") + return cast(DistributionName, distribution_name) diff --git a/tests/fixtures/simple_project/dist/simple-project-1.2.3.tar.gz b/tests/fixtures/simple_project/dist/simple_project-1.2.3.tar.gz similarity index 100% rename from tests/fixtures/simple_project/dist/simple-project-1.2.3.tar.gz rename to tests/fixtures/simple_project/dist/simple_project-1.2.3.tar.gz diff --git a/tests/integration/test_pep517.py b/tests/integration/test_pep517.py index 07e8d3bb0..0706112ba 100644 --- a/tests/integration/test_pep517.py +++ b/tests/integration/test_pep517.py @@ -48,7 +48,7 @@ def test_pep517_build_sdist( outdir=str(temporary_directory), distributions=["sdist"], ) - distributions = list(temporary_directory.glob("poetry-core-*.tar.gz")) + distributions = list(temporary_directory.glob("poetry_core-*.tar.gz")) assert len(distributions) == 1 diff --git a/tests/masonry/builders/test_complete.py b/tests/masonry/builders/test_complete.py index 40659b8ca..2d0f29026 100644 --- a/tests/masonry/builders/test_complete.py +++ b/tests/masonry/builders/test_complete.py @@ -427,7 +427,7 @@ def test_module_src() -> None: builder = Builder(Factory().create_poetry(module_path)) builder.build(fmt="all") - sdist = module_path / "dist" / "module-src-0.1.tar.gz" + sdist = module_path / "dist" / "module_src-0.1.tar.gz" assert sdist.exists() @@ -451,7 +451,7 @@ def test_package_src() -> None: builder = Builder(Factory().create_poetry(module_path)) builder.build(fmt="all") - sdist = module_path / "dist" / "package-src-0.1.tar.gz" + sdist = module_path / "dist" / "package_src-0.1.tar.gz" assert sdist.exists() @@ -476,7 +476,7 @@ def test_split_source() -> None: builder = Builder(Factory().create_poetry(module_path)) builder.build(fmt="all") - sdist = module_path / "dist" / "split-source-0.1.tar.gz" + sdist = module_path / "dist" / "split_source-0.1.tar.gz" assert sdist.exists() @@ -522,7 +522,7 @@ def test_package_with_include(mocker: MockerFixture) -> None: builder = Builder(Factory().create_poetry(module_path)) builder.build(fmt="all") - sdist = fixtures_dir / "with-include" / "dist" / "with-include-1.2.3.tar.gz" + sdist = fixtures_dir / "with-include" / "dist" / "with_include-1.2.3.tar.gz" assert sdist.exists() @@ -589,7 +589,7 @@ def test_respect_format_for_explicit_included_files() -> None: builder = Builder(Factory().create_poetry(module_path)) builder.build(fmt="all") - sdist = module_path / "dist" / "exclude-whl-include-sdist-0.1.0.tar.gz" + sdist = module_path / "dist" / "exclude_whl_include_sdist-0.1.0.tar.gz" assert sdist.exists() diff --git a/tests/masonry/builders/test_sdist.py b/tests/masonry/builders/test_sdist.py index d8d5010de..ba56df925 100644 --- a/tests/masonry/builders/test_sdist.py +++ b/tests/masonry/builders/test_sdist.py @@ -255,7 +255,7 @@ def test_package() -> None: builder = SdistBuilder(poetry) builder.build() - sdist = fixtures_dir / "complete" / "dist" / "my-package-1.2.3.tar.gz" + sdist = fixtures_dir / "complete" / "dist" / "my_package-1.2.3.tar.gz" assert sdist.exists() @@ -272,7 +272,7 @@ def test_sdist_reproducibility() -> None: builder = SdistBuilder(poetry) builder.build() - sdist = fixtures_dir / "complete" / "dist" / "my-package-1.2.3.tar.gz" + sdist = fixtures_dir / "complete" / "dist" / "my_package-1.2.3.tar.gz" assert sdist.exists() @@ -388,7 +388,7 @@ def test_with_src_module_file() -> None: builder.build() - sdist = fixtures_dir / "source_file" / "dist" / "module-src-0.1.tar.gz" + sdist = fixtures_dir / "source_file" / "dist" / "module_src-0.1.tar.gz" assert sdist.exists() @@ -413,7 +413,7 @@ def test_with_src_module_dir() -> None: builder.build() - sdist = fixtures_dir / "source_package" / "dist" / "package-src-0.1.tar.gz" + sdist = fixtures_dir / "source_package" / "dist" / "package_src-0.1.tar.gz" assert sdist.exists() @@ -465,7 +465,7 @@ def get_ignored_files(self, folder: Path | None = None) -> list[str]: builder.build() sdist = ( - fixtures_dir / "default_with_excluded_data" / "dist" / "my-package-1.2.3.tar.gz" + fixtures_dir / "default_with_excluded_data" / "dist" / "my_package-1.2.3.tar.gz" ) assert sdist.exists() @@ -499,7 +499,7 @@ def test_src_excluded_nested_data() -> None: builder = SdistBuilder(poetry) builder.build() - sdist = module_path / "dist" / "my-package-1.2.3.tar.gz" + sdist = module_path / "dist" / "my_package-1.2.3.tar.gz" assert sdist.exists() @@ -554,7 +554,7 @@ def test_includes() -> None: builder.build() - sdist = fixtures_dir / "with-include" / "dist" / "with-include-1.2.3.tar.gz" + sdist = fixtures_dir / "with-include" / "dist" / "with_include-1.2.3.tar.gz" assert sdist.exists() @@ -574,7 +574,7 @@ def test_includes_with_inline_table() -> None: fixtures_dir / "with_include_inline_table" / "dist" - / "with-include-1.2.3.tar.gz" + / "with_include-1.2.3.tar.gz" ) assert sdist.exists() @@ -608,7 +608,7 @@ def test_sdist_package_pep_561_stub_only() -> None: builder = SdistBuilder(poetry) builder.build() - sdist = root / "dist" / "pep-561-stubs-0.1.tar.gz" + sdist = root / "dist" / "pep_561_stubs-0.1.tar.gz" assert sdist.exists() @@ -626,7 +626,7 @@ def test_sdist_disable_setup_py() -> None: builder = SdistBuilder(poetry) builder.build() - sdist = module_path / "dist" / "my-package-1.2.3.tar.gz" + sdist = module_path / "dist" / "my_package-1.2.3.tar.gz" assert sdist.exists() diff --git a/tests/masonry/utils/test_helpers.py b/tests/masonry/utils/test_helpers.py index 8bc636271..b03ff39dd 100644 --- a/tests/masonry/utils/test_helpers.py +++ b/tests/masonry/utils/test_helpers.py @@ -1,5 +1,7 @@ from __future__ import annotations +import warnings + import pytest from poetry.core.masonry.utils.helpers import escape_name @@ -16,4 +18,6 @@ ], ) def test_escape_name(name: str, expected: str) -> None: - assert escape_name(name) == expected + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + assert escape_name(name) == expected