Skip to content

Commit

Permalink
Support extras and python on poetry deps
Browse files Browse the repository at this point in the history
  • Loading branch information
thatch committed Aug 30, 2024
1 parent 271a5a6 commit c096436
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 21 deletions.
43 changes: 35 additions & 8 deletions metadata_please/source_checkout.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
Notably, does not read setup.py or attempt to emulate anything that can't be read staticly.
"""

import re
from pathlib import Path

try:
Expand All @@ -24,16 +24,29 @@

from .types import BasicMetadata

OPERATOR_RE = re.compile(r"([<>=~]+)(\d.*)")


def combine_markers(*markers: str) -> str:
filtered_markers = [m for m in markers if m and m.strip()]
if len(filtered_markers) == 0:
return ""
elif len(filtered_markers) == 1:
return filtered_markers[0]
else:
return " and ".join(f"({m})" for m in filtered_markers)


def merge_markers(extra_name: str, value: str) -> str:
def merge_extra_marker(extra_name: str, value: str) -> str:
"""Simulates what a dist-info requirement string would look like if also restricted to an extra."""
if ";" not in value:
return f'{value} ; extra == "{extra_name}"'
else:
a, _, b = value.partition(";")
a = a.strip()
b = b.strip()
return f'{a} ; ({b}) and extra == "{extra_name}"'
c = f'extra == "{extra_name}"'
return f"{a} ; {combine_markers(b, c)}"


def from_source_checkout(path: Path) -> bytes:
Expand Down Expand Up @@ -61,7 +74,7 @@ def from_pep621_checkout(path: Path) -> bytes:
extra_name = canonicalize_name(k)
buf.append(f"Provides-Extra: {extra_name}\n")
for i in v:
buf.append("Requires-Dist: " + merge_markers(extra_name, i) + "\n")
buf.append("Requires-Dist: " + merge_extra_marker(extra_name, i) + "\n")

return "".join(buf).encode("utf-8")

Expand Down Expand Up @@ -127,10 +140,21 @@ def from_poetry_checkout(path: Path) -> bytes:
extras = "[%s]" % (",".join(v["extras"]))
else:
extras = ""
markers = v.get("markers", "")
python = v.get("python", "")
if python:
m = OPERATOR_RE.fullmatch(python)
assert m is not None
# TODO do ^/~ work on python version?
python = f"python_version {m.group(1)} '{m.group(2)}'"
markers = combine_markers(markers, python)
if markers:
markers = " ; " + markers
optional = v.get("optional", False)
else:
version = v
extras = ""
markers = ""
optional = False

if not version:
Expand All @@ -150,17 +174,18 @@ def from_poetry_checkout(path: Path) -> bytes:
version = "==" + version

if optional:
saved_extra_constraints[k] = f"{extras}{version}"
saved_extra_constraints[k] = (f"{extras}{version}", markers)
else:
buf.append(f"Requires-Dist: {k}{extras}{version}\n")
buf.append(f"Requires-Dist: {k}{extras}{version}{markers}\n")

for k, v in doc.get("tool", {}).get("poetry", {}).get("extras", {}).items():
k = canonicalize_name(k)
buf.append(f"Provides-Extra: {k}\n")
for vi in v:
vi = canonicalize_name(vi)
constraints, markers = saved_extra_constraints[vi]
buf.append(
f"Requires-Dist: {vi}{merge_markers(k, saved_extra_constraints[vi])}"
f"Requires-Dist: {vi}{constraints}{merge_extra_marker(k, markers)}"
)

return "".join(buf).encode("utf-8")
Expand Down Expand Up @@ -195,7 +220,9 @@ def from_setup_cfg_checkout(path: Path) -> bytes:
for i in v.splitlines():
i = i.strip()
if i:
buf.append("Requires-Dist: " + merge_markers(extra_name, i) + "\n")
buf.append(
"Requires-Dist: " + merge_extra_marker(extra_name, i) + "\n"
)

return "".join(buf).encode("utf-8")

Expand Down
43 changes: 30 additions & 13 deletions metadata_please/tests/source_checkout.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,25 @@ def test_pep621_extras(self) -> None:
Path(d, "pyproject.toml").write_text(
"""\
[project]
dependencies = ["x"]
dependencies = ["x", "y ; platform_system != 'Windows'"]
[project.optional-dependencies]
dev = ["Foo <= 2"]
marker = ["Bar ; python_version < '3'", "Baz <= 2; python_version < '3'"]
"""
)
rv = basic_metadata_from_source_checkout(Path(d))
self.assertEqual(
BasicMetadata(["x", 'Foo <= 2 ; extra == "dev"'], frozenset(["dev"])),
basic_metadata_from_source_checkout(Path(d)),
[
"x",
"y ; platform_system != 'Windows'",
'Foo <= 2 ; extra == "dev"',
"Bar ; (python_version < '3') and (extra == \"marker\")",
"Baz <= 2 ; (python_version < '3') and (extra == \"marker\")",
],
rv.reqs,
)
self.assertEqual(frozenset({"dev", "marker"}), rv.provides_extra)

def test_poetry_full(self) -> None:
with tempfile.TemporaryDirectory() as d:
Expand All @@ -45,6 +54,8 @@ def test_poetry_full(self) -> None:
c = "~1.2.3"
c2 = "~1.2"
c3 = "~1"
d = {version="2", python="<3.11"}
e = {version="2", markers="sys_platform == 'darwin'"}
skipped = {git = "..."}
complex = {extras=["bar", "baz"], version="2"}
opt = { version = "^2.9", optional = true}
Expand All @@ -64,6 +75,8 @@ def test_poetry_full(self) -> None:
"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'",
"complex[bar,baz]==2",
'opt>=2.9,<3 ; extra == "foo"',
],
Expand Down Expand Up @@ -98,17 +111,21 @@ def test_setuptools_extras(self) -> None:
# comment after
marker =
Bar ; python_version < "3"
Baz <= 2; python_version < "3"
"""
)
rv = basic_metadata_from_source_checkout(Path(d))
self.assertEqual(
BasicMetadata(
[
"x",
"y",
'Foo <= 2 ; extra == "dev"',
'Bar ; (python_version < "3") and extra == "marker"',
],
frozenset(["dev", "marker"]),
),
basic_metadata_from_source_checkout(Path(d)),
[
"x",
"y",
'Foo <= 2 ; extra == "dev"',
'Bar ; (python_version < "3") and (extra == "marker")',
'Baz <= 2 ; (python_version < "3") and (extra == "marker")',
],
rv.reqs,
)
self.assertEqual(
frozenset({"dev", "marker"}),
rv.provides_extra,
)

0 comments on commit c096436

Please sign in to comment.