Yanked releases skipped in ranges but allowed on exact pins under PEP 592
0 reputation · 24 Jun 2022, 13:21 UTC
0 reputation · 24 Jun 2022, 13:21 UTC
PyPI implements PEP 592 yanking, which lets a maintainer mark a release as yanked with a free-form reason without removing the files. The marker is exposed via the project JSON API and on the project page.
Under PEP 592 semantics, installers that support the convention generally avoid yanked releases when resolving a version range, while still permitting installation when a version is exactly pinned or present in a lockfile. Yanking is distinct from deletion, and the yank reason has no enforced structure.
Behavior is installer-dependent and can vary across environments that do not implement PEP 592 or use older resolver logic. Yanking does not remove artifacts from mirrors, caches, or existing environments.
For teams defining dependency policy, the unresolved decision is how to handle pinned yanked versions, since pip installs them silently by default and policy enforcement requires additional tooling.
What is the intended treatment for an exact pin to a yanked release in a build policy? How should teams consistently surface yank reasons when the field is free-form? What expectations should be set for installers that do not respect PEP 592 yank markers?
34275 reputation · 24 Jun 2022, 20:40 UTC
PEP 592 marks a release as yanked without deleting its files. Installers that support the convention treat a yanked release as undesirable when resolving a range (e.g., pkg>=1.0,<2.0), but they still honor an exact pin because the pin is a hard requirement. Consequently, pip install package==1.2.3 will succeed even if 1.2.3 is yanked, unless the installer is explicitly configured to treat a yank as an error.
For a team that enforces a dependency policy, the safest approach is to treat any lockfile entry whose yank_reason is non‑empty as a compliance issue, regardless of the installer’s behaviour. The policy check should run after resolution, not during lockfile generation, because a lockfile can contain a yanked version that the installer later installs without warning.
The yank_reason field is free‑form text. It can be retrieved via the PyPI JSON API:
curl -s https://pypi.org/pypi/<package>/json | jq '.releases["<ver>"][0].yank_reason'
Teams can surface the reason in audit logs, CI console output, or a compliance dashboard. Store the plain‑text string next to the affected package entry; no parsing logic is required because the format is unstructured.
pip<24.0, some conda builds, or custom resolvers) may silently install a yanked release.yank_reason is detected.pip install --no-deps --dry-run package==1.2.3 (pip ≥24.0 will emit a warning if the version is yanked).yank_reason via the JSON API as shown above.yank_reason and fails if present.Implement a policy enforcement step that inspects the lockfile after resolution. If any entry has a non‑empty yank_reason, log the reason and fail the build. This guarantees that exact‑pinned yanked releases cannot slip through silently.
Do you know which installer and version you are using in your CI environment? That detail can influence whether you need an additional wrapper or whether the default installer will already warn you.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.