diff --git a/metadata_please/source_checkout.py b/metadata_please/source_checkout.py index 497e643..92da2d5 100644 --- a/metadata_please/source_checkout.py +++ b/metadata_please/source_checkout.py @@ -25,6 +25,7 @@ from configparser import NoOptionError, NoSectionError, RawConfigParser from packaging.utils import canonicalize_name +from packaging.version import Version from .source_checkout_ast import SetupFindingVisitor, UNKNOWN @@ -139,22 +140,41 @@ def _translate_caret(specifier: str) -> str: Given a string like "^0.2.3" returns ">=0.2.3,<0.3.0". """ assert "," not in specifier - parts = specifier[1:].split(".") - while len(parts) < 3: - parts.append("0") - - for i in range(len(parts)): - if parts[i] != "0": - # The docs are not super clear about how this behaves, but let's - # assume integer-valued parts and just let the exception raise - # otherwise. - incremented = parts[:] - incremented[i] = str(int(parts[i]) + 1) - del incremented[i + 1 :] - incremented_version = ".".join(incremented) - break + + version = Version(specifier[1:]) + + # version.release takes out the pre- and post- parts and leaves only numbers + version_parts = list(version.release) + + if version.is_prerelease or version.is_postrelease: + # Return next version, incrementing the least significant number + version_parts[-1] += 1 + else: - raise ValueError("All components were zero?") + if version.major == version.minor == version.micro == 0: + raise ValueError("All components were zero?") + + if version.major > 0 or version.minor == 0: + # Next major version + version_parts[0] += 1 + + # Set the rest of the values to 0 + for i in range(1, len(version_parts)): + version_parts[i] = 0 + + elif version.minor > 0 or version.micro == 0: + # Next minor version. + version_parts[1] += 1 + + # Set the rest of the values to 0 + for i in range(2, len(version_parts)): + version_parts[i] = 0 + + else: + # Next patch version + version_parts[2] += 1 + + incremented_version = ".".join([str(i) for i in version_parts]) return f">={specifier[1:]},<{incremented_version}" @@ -213,7 +233,27 @@ def from_poetry_checkout(path: Path) -> bytes: optional = False if not version: - # e.g. git, path or url dependencies, skip for now + # e.g. git, path or url dependencies + if "git" in v: + git_link = f"git+{v['git']}" + + # from both poetry and pypa docs, seems like only one of the following should be specified + revision = v.get("rev") or v.get("tag") or v.get("branch") + if revision: + git_link += f"@{revision}" + + if "subdirectory" in v: + git_link += f"#subdirectory={v['subdirectory']}" + + buf.append(f"Requires-Dist: {k} @ {git_link}\n") + + # Still not sure about the PEP-508 form that these are supposed to take + # elif "path" in v: + # buf.append(f"Requires-Dist: {v['path']}\n") + # + # elif "url" in v: + # buf.append(f"Requires-Dist: {v['url']}\n") + # continue # https://python-poetry.org/docs/dependency-specification/#version-constraints diff --git a/metadata_please/tests/source_checkout.py b/metadata_please/tests/source_checkout.py index 8fb0191..19d4e27 100644 --- a/metadata_please/tests/source_checkout.py +++ b/metadata_please/tests/source_checkout.py @@ -105,12 +105,15 @@ def test_poetry_full(self) -> None: a2 = "*" b = "^1.2.3" b2 = "^0.2.3" +b3 = "^0.44b0" c = "~1.2.3" c2 = "~1.2" c3 = "~1" d = {version="2", python="<3.11"} e = {version="2", markers="sys_platform == 'darwin'"} -skipped = {git = "..."} +skipped = {git = "...", tag = "12345"} +my-url-package = { url = "https://example.com/my-package-0.1.0.tar.gz" } +my-path-package = { path = "../my-package/dist/my-other-package-0.1.0.tar.gz" } complex = {extras=["bar", "baz"], version="2"} opt = { version = "^2.9", optional = true} unused-extra = { version = "2", optional = true } @@ -124,15 +127,17 @@ def test_poetry_full(self) -> None: [ "a==1.0", "a2", - "b>=1.2.3,<2", - "b2>=0.2.3,<0.3", + "b>=1.2.3,<2.0.0", + "b2>=0.2.3,<0.3.0", + "b3>=0.44b0,<0.45", "c>=1.2.3,<1.3", "c2>=1.2,<1.3", "c3>=1,<2", "d==2 ; python_version < '3.11'", "e==2 ; sys_platform == 'darwin'", + "skipped @ git+...@12345", "complex[bar,baz]==2", - 'opt>=2.9,<3 ; extra == "foo"', + 'opt>=2.9,<3.0 ; extra == "foo"', ], rv.reqs, )