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..0b84a3396 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,33 @@ 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() + + +# 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 ... +def distribution_name(name: NormalizedName) -> DistributionName: + 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 0517acd0b..a54a76a9e 100644 --- a/tests/masonry/builders/test_complete.py +++ b/tests/masonry/builders/test_complete.py @@ -425,7 +425,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() @@ -449,7 +449,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() @@ -474,7 +474,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() @@ -520,7 +520,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() @@ -587,7 +587,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 66785c91f..5a6278dde 100644 --- a/tests/masonry/builders/test_sdist.py +++ b/tests/masonry/builders/test_sdist.py @@ -253,7 +253,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() @@ -270,7 +270,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() @@ -386,7 +386,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() @@ -411,7 +411,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() @@ -459,7 +459,7 @@ def test_default_with_excluded_data(mocker: MockerFixture) -> None: 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() @@ -493,7 +493,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() @@ -548,7 +548,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() @@ -568,7 +568,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() @@ -602,7 +602,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() @@ -620,7 +620,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()