Managing Published Releases
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the Python Reference bibliography. |
A release on PyPI is permanent in one direction: files can be removed, never replaced. What maintainers can do after publication is limited and differs a lot in its effect on users. This page covers those actions as documented on 2026-10-22. The yanking behaviour was reproduced on Linux with pip 26.2.2 on CPython 3.14.6, against a local static index; the PyPI examples are read-only queries of PyPI’s public APIs; no release was yanked, deleted or archived on PyPI.
Yanking (PEP 592)
A yanked release stays on the index but installers skip it, unless it is the only release matching a pin with == or ===.
That keeps existing lock files working while new installs avoid the bad release. On PyPI you yank whole releases (not single
files) from the release management page, with an optional reason that installers show.
A static simple index with birdtally 0.1.0 and a yanked 0.1.1 (the PEP 503 link carries data-yanked="broken CSV parsing"):
pip install --dry-run --no-deps --index-url http://127.0.0.1:8085/simple/ birdtally
pip install --dry-run --no-deps --index-url http://127.0.0.1:8085/simple/ birdtally==0.1.1
pip install --dry-run --no-deps --index-url http://127.0.0.1:8085/simple/ "birdtally>=0.1.1"
Would install birdtally-0.1.0
WARNING: The candidate selected for download or install is a yanked version: 'birdtally' candidate (version 0.1.1 at http://127.0.0.1:8085/files/birdtally-0.1.1-py3-none-any.whl#sha256=b64d4d23… (from http://127.0.0.1:8085/simple/birdtally/) (requires-python:>=3.10))
Reason for being yanked: broken CSV parsing
Would install birdtally-0.1.1
ERROR: Ignored the following yanked versions: 0.1.1
ERROR: Could not find a version that satisfies the requirement birdtally>=0.1.1 (from versions: 0.1.0)
ERROR: No matching distribution found for birdtally>=0.1.1
The latest is 0.1.0 because 0.1.1 is yanked; the exact pin still gets 0.1.1, with a warning; a range does not. pip’s
--report marks the choice: "is_yanked": true for the pinned install. On PyPI, the JSON simple API exposes the same flag per
file, for example for requests:
curl -s -H "Accept: application/vnd.pypi.simple.v1+json" https://pypi.org/simple/requests/
('requests-2.32.0-py3-none-any.whl', 'Yanked due to conflicts with CVE-2024-35195 mitigation')
('requests-2.32.0.tar.gz', 'Yanked due to conflicts with CVE-2024-35195 mitigation')
…
(the yanked field of each file, extracted). Yank a release that is broken or uninstallable, that breaks its compatibility
promise by accident, or that has a security vulnerability; then publish a fixed release. Yanking does not free storage.
Deleting
Deleting a file, a release or a project is permanent and irreversible, without exception: PyPI’s administrators cannot restore it. A deleted project’s name becomes free for anyone to register, and deleted filenames can never be uploaded again. Deletion breaks every pinned install of those versions. Prefer yanking for a bad release and archiving for an abandoned project; delete only what must not be distributed at all (a leaked secret, files published by mistake), and rotate the secret anyway.
Archiving, quarantine and status markers (PEP 792)
| Status | Who sets it, since | Effect |
|---|---|---|
|
default |
Uploads and downloads allowed. |
|
owners, 2025-01-30 |
No new uploads; existing files still installable; hidden from search. For projects that will receive no more updates. |
|
PyPI administrators, 2024-12-30 |
Not installable and not modifiable while PyPI reviews suspected malware or abuse; a single release can be quarantined. |
|
(specified) |
Like active; installers may warn that the project is obsolete. |
PEP 792 (statuses in the index APIs, 2025-08-14) puts the status in the simple API, where installers can read it:
{'meta': {'_last-serial': 25862117, 'api-version': '1.4'}, 'name': 'sampleproject', 'project-status': {'status': 'active'}}
(the JSON simple page of sampleproject without its file list).
Adding files to an existing release
Since 2026-07-22 PyPI refuses new files for a release that is more than 14 days old; the PyPI blog adds that users "should not
yet rely" on this as defined semantics. A wheel for a new Python version or platform (say cp315 wheels for an extension built
before 3.15 existed) therefore needs a new release, typically a post-release (1.4.0.post1) with the same code, built and
uploaded together.
Storage limits
PyPI allows 100 MB per file and 10 GB per project by default. Free space by deleting old releases or individual files (with the consequences above); yanking does not help. Larger limits are requested through PyPI’s support tracker, per index (PyPI and TestPyPI separately), after a release under the limit exists. Projects owned by an organization are transferred or deleted by the organization’s owners from the organization’s project settings.
Download statistics (not run here)
PyPI logs every download to the public BigQuery table bigquery-public-data.pypi.file_downloads (one row per download with
timestamp, file.project, file.version, details.installer.name, details.python and more). A Google Cloud project with the
BigQuery API enabled can query it within the free tier:
#standardSQL
SELECT file.version, COUNT(*) AS downloads
FROM `bigquery-public-data.pypi.file_downloads`
WHERE file.project = 'birdtally'
AND details.installer.name = 'pip'
AND DATE(timestamp) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY) AND CURRENT_DATE()
GROUP BY file.version
ORDER BY downloads DESC
Caveats: downloads are not users (CI runs and mirrors dominate many counts), mirrors and caches hide downloads, and data before
2018-07-26 is under-reported. Tools: pypinfo (a command-line front end), pandas-gbq (query into a DataFrame), the
google-cloud-bigquery client, and ClickPy (a public ClickHouse-based dashboard of the same data).
References
-
The PyPI blog (archival 2025-01-30, quarantine 2024-12-30, the 14-day rule 2026-07-22)