#6158·pixi

Per-index exclude-newer for extra-index-urls

Author: christhorn2Created May 20, 2026Updated Sep 17, 2026
Labelsenhancement

Problem description

Summary

Allow [tool.pixi.pypi-options].extra-index-urls entries to be inline tables that carry their own exclude-newer value, mirroring ChannelInlineTable.exclude-newer already supported for conda channels.

Motivation

[tool.pixi.workspace].exclude-newer and the per-package [tool.pixi.pypi-exclude-newer] table (added in 0.67) both require upload-time metadata in the index response to evaluate the cutoff. When a private/internal PyPI mirror does not expose upload-time (which is common — Artifactory's pypi-virtual repo, for example, does not), every version of every package served from that mirror becomes ineligible. The solve fails with Because there is no version of <pkg>==X.Y.Z and you require <pkg>==X.Y.Z, we can conclude that your requirements are unsatisfiable, even when the pin is exact and the version is unambiguously present.

There is currently no way to apply yank protection to public-index packages while leaving private-index packages alone.

Proposed syntax

toml
[tool.pixi.pypi-options]
extra-index-urls = [
    "https://pypi.org/simple",                          # filter applied via global exclude-newer
    { url = "https://artifactory.internal/simple", exclude-newer = false },
]

exclude-newer = false (or omitted, with appropriate default) → no filter on packages served from that index. A string value would set a custom cutoff for that index. Mirrors the existing ChannelInlineTable:

toml
channels = [
    "conda-forge",
    { channel = "internal", exclude-newer = false },
]

Alternatives considered

  • [tool.pixi.pypi-exclude-newer] = { pkg = "9999-01-01" }: doesn't help because uv still excludes versions whose upload-time is unparseable/missing, regardless of the per-package cutoff value.
  • [tool.pixi.pypi-exclude-newer] = { pkg = "0d" }: same.
  • Enumerating every public-index package explicitly and omitting private-index ones: works as a script-level workaround but doesn't cover transitive deps and doesn't generalize.

Use case

We rewrite version pins in esr-pkg/pyproject.toml periodically via a bump-constraints script that strips == pins, calls pixi update, and rewrites the resolved versions. We want a 7-day soak window on every public-index package (PyPI yanks happen often enough to be a real concern), but our manifest also depends on internal-mirror packages whose metadata doesn't include upload-time. The per-index lever would let us write one line in the manifest and stop maintaining a per-package exemption list in the bump script.