diff --git a/src/poetry/core/masonry/builders/sdist.py b/src/poetry/core/masonry/builders/sdist.py index 7aa1e3313..d2809b5e9 100644 --- a/src/poetry/core/masonry/builders/sdist.py +++ b/src/poetry/core/masonry/builders/sdist.py @@ -204,7 +204,7 @@ def build_setup(self) -> bytes: return SETUP.format( before="\n".join(before), name=str(self._meta.name), - version=str(self._meta.version), + version=self._meta.version, description=str(self._meta.summary), long_description=str(self._meta.description), author=str(self._meta.author), diff --git a/src/poetry/core/masonry/builders/wheel.py b/src/poetry/core/masonry/builders/wheel.py index 01533e7b6..705f7f1ed 100644 --- a/src/poetry/core/masonry/builders/wheel.py +++ b/src/poetry/core/masonry/builders/wheel.py @@ -24,7 +24,6 @@ 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 escape_version from poetry.core.masonry.utils.helpers import normalize_file_permissions from poetry.core.masonry.utils.package_include import PackageInclude from poetry.core.semver.helpers import parse_constraint @@ -282,7 +281,7 @@ def wheel_data_folder(self) -> str: @property def wheel_filename(self) -> str: name = escape_name(self._package.pretty_name) - version = escape_version(self._meta.version) + version = self._meta.version return f"{name}-{version}-{self.tag}.whl" def supports_python2(self) -> bool: @@ -292,9 +291,8 @@ def supports_python2(self) -> bool: def dist_info_name(self, distribution: str, version: str) -> str: escaped_name = escape_name(distribution) - escaped_version = escape_version(version) - return f"{escaped_name}-{escaped_version}.dist-info" + return f"{escaped_name}-{version}.dist-info" @property def tag(self) -> str: diff --git a/src/poetry/core/masonry/metadata.py b/src/poetry/core/masonry/metadata.py index 33c76d2e3..1ef34c2c5 100644 --- a/src/poetry/core/masonry/metadata.py +++ b/src/poetry/core/masonry/metadata.py @@ -49,13 +49,12 @@ class Metadata: def from_package(cls, package: Package) -> Metadata: from packaging.utils import canonicalize_name - from poetry.core.utils.helpers import normalize_version from poetry.core.version.helpers import format_python_constraint meta = cls() meta.name = canonicalize_name(package.name) - meta.version = normalize_version(package.version.text) + meta.version = package.version.to_string() meta.summary = package.description if package.readmes: descriptions = [] diff --git a/src/poetry/core/masonry/utils/helpers.py b/src/poetry/core/masonry/utils/helpers.py index b79089f3e..7a3738c6a 100644 --- a/src/poetry/core/masonry/utils/helpers.py +++ b/src/poetry/core/masonry/utils/helpers.py @@ -1,6 +1,7 @@ from __future__ import annotations import re +import warnings def normalize_file_permissions(st_mode: int) -> int: @@ -25,6 +26,11 @@ def escape_version(version: str) -> str: the escaping specification in :pep:`427#escaping-and-unicode` because this conflicts with :pep:`440#local-version-identifiers`. """ + warnings.warn( + "escape_version() is deprecated. Use Version.parse().to_string() instead.", + DeprecationWarning, + stacklevel=2, + ) return re.sub(r"[^\w\d.+]+", "_", version, flags=re.UNICODE) diff --git a/src/poetry/core/utils/helpers.py b/src/poetry/core/utils/helpers.py index 3e03d0c28..dd41b2459 100644 --- a/src/poetry/core/utils/helpers.py +++ b/src/poetry/core/utils/helpers.py @@ -5,6 +5,7 @@ import stat import tempfile import unicodedata +import warnings from contextlib import contextmanager from pathlib import Path @@ -25,6 +26,11 @@ def module_name(name: str) -> str: def normalize_version(version: str) -> str: + warnings.warn( + "normalize_version() is deprecated. Use Version.parse().to_string() instead.", + DeprecationWarning, + stacklevel=2, + ) return PEP440Version.parse(version).to_string() diff --git a/tests/masonry/builders/fixtures/epoch/README.rst b/tests/masonry/builders/fixtures/epoch/README.rst new file mode 100644 index 000000000..ce1f88eca --- /dev/null +++ b/tests/masonry/builders/fixtures/epoch/README.rst @@ -0,0 +1,2 @@ +Epoch +===== diff --git a/tests/masonry/builders/fixtures/epoch/epoch.py b/tests/masonry/builders/fixtures/epoch/epoch.py new file mode 100644 index 000000000..8de3a59b0 --- /dev/null +++ b/tests/masonry/builders/fixtures/epoch/epoch.py @@ -0,0 +1,3 @@ +"""Example module""" + +__version__ = "1!2.0" diff --git a/tests/masonry/builders/fixtures/epoch/pyproject.toml b/tests/masonry/builders/fixtures/epoch/pyproject.toml new file mode 100644 index 000000000..87c34f31d --- /dev/null +++ b/tests/masonry/builders/fixtures/epoch/pyproject.toml @@ -0,0 +1,12 @@ +[tool.poetry] +name = "epoch" +version = "1!2.0" +description = "Some description." +authors = [ + "Sébastien Eustace " +] +license = "MIT" + +readme = "README.rst" + +homepage = "https://python-poetry.org/" diff --git a/tests/masonry/builders/test_wheel.py b/tests/masonry/builders/test_wheel.py index bde27857b..7efa24166 100644 --- a/tests/masonry/builders/test_wheel.py +++ b/tests/masonry/builders/test_wheel.py @@ -72,6 +72,18 @@ def test_wheel_prerelease() -> None: assert whl.exists() +def test_wheel_epoch() -> None: + module_path = fixtures_dir / "epoch" + WheelBuilder.make(Factory().create_poetry(module_path)) + + whl = module_path / "dist" / "epoch-1!2.0-py2.py3-none-any.whl" + + assert whl.exists() + + with zipfile.ZipFile(str(whl)) as z: + assert "epoch-1!2.0.dist-info/METADATA" in z.namelist() + + def test_wheel_excluded_data() -> None: module_path = fixtures_dir / "default_with_excluded_data_toml" WheelBuilder.make(Factory().create_poetry(module_path)) diff --git a/tests/masonry/utils/test_helpers.py b/tests/masonry/utils/test_helpers.py index 8be13c40a..8bc636271 100644 --- a/tests/masonry/utils/test_helpers.py +++ b/tests/masonry/utils/test_helpers.py @@ -3,24 +3,6 @@ import pytest from poetry.core.masonry.utils.helpers import escape_name -from poetry.core.masonry.utils.helpers import escape_version - - -@pytest.mark.parametrize( - "version,expected", - [ - ("1.2.3", "1.2.3"), - ("1.2.3_1", "1.2.3_1"), - ("1.2.3-1", "1.2.3_1"), - ("1.2.3-1", "1.2.3_1"), - ("2022.2", "2022.2"), - ("12.20.12-----451---14-1-4-41", "12.20.12_451_14_1_4_41"), - ("1.0b2.dev1", "1.0b2.dev1"), - ("1.0+abc.7", "1.0+abc.7"), - ], -) -def test_escape_version(version: str, expected: str) -> None: - assert escape_version(version) == expected @pytest.mark.parametrize( diff --git a/tests/semver/test_version.py b/tests/semver/test_version.py index 99231c958..31a8bffdb 100644 --- a/tests/semver/test_version.py +++ b/tests/semver/test_version.py @@ -288,3 +288,73 @@ def test_difference() -> None: assert ( v.difference(VersionRange(Version.parse("1.4.0"), Version.parse("3.0.0"))) == v ) + + +@pytest.mark.parametrize( + "version,normalized_version", + [ + ( # already normalized version + "1!2.3.4.5.6a7.post8.dev9+local1.123.abc", + "1!2.3.4.5.6a7.post8.dev9+local1.123.abc", + ), + # PEP 440 Normalization + # Case sensitivity + ("1.1RC1", "1.1rc1"), + # Integer Normalization + ("00", "0"), + ("09000", "9000"), + ("1.0+foo0100", "1.0+foo0100"), + # Pre-release separators + ("1.1.a1", "1.1a1"), + ("1.1-a1", "1.1a1"), + ("1.1_a1", "1.1a1"), + ("1.1a.1", "1.1a1"), + ("1.1a-1", "1.1a1"), + ("1.1a_1", "1.1a1"), + # Pre-release spelling + ("1.1alpha1", "1.1a1"), + ("1.1beta2", "1.1b2"), + ("1.1c3", "1.1rc3"), + ("1.1pre4", "1.1rc4"), + ("1.1preview5", "1.1rc5"), + # Implicit pre-release number + ("1.2a", "1.2a0"), + # Post release separators + ("1.2.post2", "1.2.post2"), + ("1.2-post2", "1.2.post2"), + ("1.2_post2", "1.2.post2"), + ("1.2post.2", "1.2.post2"), + ("1.2post-2", "1.2.post2"), + ("1.2post_2", "1.2.post2"), + # Post release spelling + ("1.0-r4", "1.0.post4"), + ("1.0-rev4", "1.0.post4"), + # Implicit post release number + ("1.2.post", "1.2.post0"), + # Implicit post releases + ("1.0-1", "1.0.post1"), + # Development release separators + ("1.2.dev2", "1.2.dev2"), + ("1.2-dev2", "1.2.dev2"), + ("1.2_dev2", "1.2.dev2"), + ("1.2dev.2", "1.2.dev2"), + ("1.2dev-2", "1.2.dev2"), + ("1.2dev_2", "1.2.dev2"), + # Implicit development release number + ("1.2.dev", "1.2.dev0"), + # Local version segments + ("1.0+ubuntu-1", "1.0+ubuntu.1"), + ("1.0+ubuntu_1", "1.0+ubuntu.1"), + # Preceding v character + ("v1.0", "1.0"), + # Leading and Trailing Whitespace + (" 1.0 ", "1.0"), + ("\t1.0\t", "1.0"), + ("\n1.0\n", "1.0"), + ("\r\n1.0\r\n", "1.0"), + ("\f1.0\f", "1.0"), + ("\v1.0\v", "1.0"), + ], +) +def test_to_string_normalizes(version: str, normalized_version: str) -> None: + assert Version.parse(version).to_string() == normalized_version diff --git a/tests/utils/test_helpers.py b/tests/utils/test_helpers.py index 2bb862add..f8fe4393c 100644 --- a/tests/utils/test_helpers.py +++ b/tests/utils/test_helpers.py @@ -8,82 +8,11 @@ import pytest from poetry.core.utils.helpers import combine_unicode -from poetry.core.utils.helpers import normalize_version from poetry.core.utils.helpers import parse_requires from poetry.core.utils.helpers import readme_content_type from poetry.core.utils.helpers import temporary_directory -@pytest.mark.parametrize( - "version,normalized_version", - [ - ( # already normalized version - "1!2.3.4.5.6a7.post8.dev9+local1.123.abc", - "1!2.3.4.5.6a7.post8.dev9+local1.123.abc", - ), - # PEP 440 Normalization - # Case sensitivity - ("1.1RC1", "1.1rc1"), - # Integer Normalization - ("00", "0"), - ("09000", "9000"), - ("1.0+foo0100", "1.0+foo0100"), - # Pre-release separators - ("1.1.a1", "1.1a1"), - ("1.1-a1", "1.1a1"), - ("1.1_a1", "1.1a1"), - ("1.1a.1", "1.1a1"), - ("1.1a-1", "1.1a1"), - ("1.1a_1", "1.1a1"), - # Pre-release spelling - ("1.1alpha1", "1.1a1"), - ("1.1beta2", "1.1b2"), - ("1.1c3", "1.1rc3"), - ("1.1pre4", "1.1rc4"), - ("1.1preview5", "1.1rc5"), - # Implicit pre-release number - ("1.2a", "1.2a0"), - # Post release separators - ("1.2.post2", "1.2.post2"), - ("1.2-post2", "1.2.post2"), - ("1.2_post2", "1.2.post2"), - ("1.2post.2", "1.2.post2"), - ("1.2post-2", "1.2.post2"), - ("1.2post_2", "1.2.post2"), - # Post release spelling - ("1.0-r4", "1.0.post4"), - ("1.0-rev4", "1.0.post4"), - # Implicit post release number - ("1.2.post", "1.2.post0"), - # Implicit post releases - ("1.0-1", "1.0.post1"), - # Development release separators - ("1.2.dev2", "1.2.dev2"), - ("1.2-dev2", "1.2.dev2"), - ("1.2_dev2", "1.2.dev2"), - ("1.2dev.2", "1.2.dev2"), - ("1.2dev-2", "1.2.dev2"), - ("1.2dev_2", "1.2.dev2"), - # Implicit development release number - ("1.2.dev", "1.2.dev0"), - # Local version segments - ("1.0+ubuntu-1", "1.0+ubuntu.1"), - ("1.0+ubuntu_1", "1.0+ubuntu.1"), - # Preceding v character - ("v1.0", "1.0"), - # Leading and Trailing Whitespace - (" 1.0 ", "1.0"), - ("\t1.0\t", "1.0"), - ("\n1.0\n", "1.0"), - ("\r\n1.0\r\n", "1.0"), - ("\f1.0\f", "1.0"), - ("\v1.0\v", "1.0"), - ], -) -def test_normalize_version(version: str, normalized_version: str) -> None: - assert normalize_version(version) == normalized_version - - def test_parse_requires() -> None: requires = """\ jsonschema>=2.6.0.0,<3.0.0.0