Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: generate provenance_url.json when installing packages(PEP 710) #3013

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions news/3013.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Produce `provenance_url.json` when installing packages as specified by [PEP 710](https://peps.python.org/pep-0710/).
8 changes: 3 additions & 5 deletions src/pdm/installers/installers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from __future__ import annotations

import json
import os
import stat
from functools import cached_property
Expand Down Expand Up @@ -151,7 +150,7 @@ def _get_link_method(cache_method: str) -> LinkMethod:
def install_wheel(
wheel: Path,
environment: BaseEnvironment,
direct_url: dict[str, Any] | None = None,
additional_metadata: dict[str, bytes] | None = None,
install_links: bool = False,
rename_pth: bool = False,
) -> str:
Expand All @@ -169,9 +168,8 @@ def install_wheel(
else:
link_method = _get_link_method(cache_method)

additional_metadata: dict[str, bytes] = {}
if direct_url is not None:
additional_metadata["direct_url.json"] = json.dumps(direct_url, indent=2).encode()
if additional_metadata is None:
additional_metadata = {}

destination = InstallDestination(
scheme_dict=environment.get_paths(dist_name),
Expand Down
11 changes: 9 additions & 2 deletions src/pdm/installers/manager.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import json
from typing import TYPE_CHECKING

from pdm import termui
Expand Down Expand Up @@ -29,10 +30,16 @@ def __init__(
def install(self, candidate: Candidate) -> Distribution:
"""Install a candidate into the environment, return the distribution"""
prepared = candidate.prepare(self.environment)
wheel = prepared.build()
additional_metadata: dict[str, bytes] = {}
if direct_url := prepared.direct_url():
additional_metadata["direct_url.json"] = json.dumps(direct_url, indent=2).encode("utf-8")
elif provenance_url := prepared.provenance_url():
additional_metadata["provenance_url.json"] = json.dumps(provenance_url, indent=2).encode("utf-8")
dist_info = install_wheel(
prepared.build(),
wheel,
self.environment,
direct_url=prepared.direct_url(),
additional_metadata=additional_metadata,
install_links=self.use_install_cache and not candidate.req.editable,
rename_pth=self.rename_pth,
)
Expand Down
26 changes: 25 additions & 1 deletion src/pdm/models/candidates.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from pdm.models.reporter import BaseReporter
from pdm.models.requirements import (
FileRequirement,
NamedRequirement,
Requirement,
VcsRequirement,
_egg_info_re,
Expand All @@ -47,6 +48,9 @@
from pdm.environments import BaseEnvironment


ALLOWED_HASHES = hashlib.algorithms_guaranteed - {"shake_128", "shake_256", "sha1", "md5"}


def _dist_info_files(whl_zip: ZipFile) -> list[str]:
"""Identify the .dist-info folder inside a wheel ZipFile."""
res = []
Expand Down Expand Up @@ -339,7 +343,9 @@
)

def direct_url(self) -> dict[str, Any] | None:
"""PEP 610 direct_url.json data"""
"""PEP 610 direct_url.json data
https://peps.python.org/pep-0610/
"""
req = self.req
if isinstance(req, VcsRequirement):
if req.editable:
Expand Down Expand Up @@ -387,6 +393,24 @@
else:
return None

def provenance_url(self) -> dict[str, Any] | None:
"""PEP 710 provenance_url.json data
https://peps.python.org/pep-0710/
"""
req = self.req
if not isinstance(req, NamedRequirement):
return None

Check warning on line 402 in src/pdm/models/candidates.py

View check run for this annotation

Codecov / codecov/patch

src/pdm/models/candidates.py#L402

Added line #L402 was not covered by tests
assert self.link is not None
hashes = {name: hashes[0] for name, hashes in (self.link.hash_option or {}).items() if name in ALLOWED_HASHES}
if not hashes:
hash_cache = self.environment.project.make_hash_cache()
hash_name, hash_value = hash_cache.get_hash(self.link, self.environment.session).split(":", 1)
hashes.update({hash_name: hash_value})
return {
"url": self.link.url_without_fragment,
"archive_info": {"hashes": hashes},
}

def build(self) -> Path:
"""Call PEP 517 build hook to build the candidate into a wheel"""
self._obtain(allow_all=False)
Expand Down
Loading