Documentation

Standards

peryx implements the Python index standards listed below. The Simple Repository API consolidates most of them. peryx serves meta.api-version 1.4 when the resolved page contains the required fields and 1.0 otherwise.

Installer request sequence

pip install requests sends this sequence to a standards-compliant index:

pypi resolve diagram pypi resolve diagram

Every hop names a standard: the page format is PEP 503/691, its fields are PEP 700, the yank markers are PEP 592, the metadata shortcut is PEP 658/714, and the filename pip parsed to pick a wheel is PEP 427. peryx sits on both sides of this conversation, a server to your clients and a client to its upstreams, which is why the table below mixes "served" and "parsed".

StandardRole in peryx
PEP 503HTML Simple API and project-name normalization
PEP 691JSON Simple API and content negotiation
PEP 629Simple API version marker
PEP 700versions, size, and upload-time fields
PEP 592Yanked-file metadata
PEP 658 and PEP 714.metadata siblings for package metadata
PEP 740Index-hosted attestations
PEP 792Project status markers
PEP 440Version ordering and Requires-Python validation
PEP 427 and PEP 625Wheel and source-distribution validation
PEP 527Zip source distributions
Core metadataMETADATA, PKG-INFO, and import declarations
PEP 508Dependency specifiers
PEP 639SPDX license expressions and files
PEP 685Normalized extra names
PEP 643Dynamic metadata fields
PEP 753Canonical project URL labels
Legacy JSON APIProject and release compatibility responses
Legacy upload APIMultipart uploads used by twine and uv publish
.pypircUpload and mirror authentication conventions

Metadata validation on upload

peryx parses the core metadata of a hosted upload and rejects the whole upload when a field is malformed, so a broken METADATA never reaches a resolver. It checks each field with the library that owns the grammar, as it does the wire formats.

  • Requires-Dist, Provides-Dist, and Obsoletes-Dist must parse as PEP 508 dependency specifiers.
  • License-Expression must be a PEP 639 SPDX expression of known, non-deprecated identifiers, and may not accompany the legacy License field.
  • Provides-Extra names collide when they normalize equal under PEP 685.
  • Dynamic may name only a field PEP 643 lets vary, never Name, Version, or Metadata-Version.
  • Classifier values must be known, non-deprecated trove classifiers, and Author-email/Maintainer-email must be RFC 822 address lists.
  • Every field must appear at or after the Metadata-Version that introduced it; a 2.5-only Import-Name on a 2.1 document is rejected.

The upload reference lists the accept and reject tables with the exact error strings.

PEP 714 and the core-metadata key

PEP 658 shipped with a bug in its dist-info-metadata key name, and PEP 714 renamed it to core-metadata. Indexes such as pypi.org emit both keys for compatibility. peryx parses both spellings, prefers core-metadata when both are present, and emits both spellings downstream for older clients.

Upstream compatibility

Some upstreams implement only part of the stack; Artifactory and GitLab may serve HTML alone. peryx negotiates JSON first and parses PEP 503 HTML as the fallback. Missing fields lower the served API version or remain absent. An upstream that advertises another Simple API major version receives a 502; peryx supports Simple API 1.x.

The discovery documents at /+api and /{route}/+api report only capabilities peryx implements today. They advertise Simple HTML/JSON, api-version 1.4, PEP 658 metadata siblings, project status, provenance, and legacy JSON. The legacy JSON responses are derived from Simple detail pages, so fields outside that source, such as ownership and vulnerability data, are empty.

Operational checks

On this page