PEP: 629
Title: Versioning PyPI's Simple API
Author: Donald Stufft <donald@stufft.io>
BDFL-Delegate: Brett Cannon <brett@python.org>
Discussions-To: https://discuss.python.org/t/pep-629-versioning-pypis-simple-api/4720
Status: Final
Type: Standards Track
Topic: Packaging
Content-Type: text/x-rst
Created: 16-Jul-2020
Post-History: 16-Jul-2020


.. note::
   This PEP was
   `accepted on 2020-08-20 <https://discuss.python.org/t/pep-629-versioning-pypis-simple-api/4720/15>`__.
   PyPI `merged an implementation <2bfa5a8c75e3af218494fe8de1eb809a43e3bbb9>`__
   on 2020-01-28, marking this PEP as "Final".


Abstract
========

This PEP proposes adding a method for versioning the simple API so
that clients can determine which features of the simple API that a
specific repository supports.


Rationale
=========

When evolving the simple API, clients wish to be able to determine
which features the repository supports. Currently there is no
mechanism to do this, except by attempting to detect new features
by looking at the data in the responses and see if it appears like
a particular feature is in use.

This works reasonably well for a modern version of a client to determine
if the repository supports all of the features it wants to implement,
however it does not do anything to tell an older version the client that
the repository supports features that it might not understand and to
allow messaging to indicate that it might not be correctly understanding
the output of the repository.

An example of a scenario where this happened was the phasing in of
python-requires metadata, while existing clients could still successfully
use the repository, they were lacking the ability to understand this new
piece of data which would have informed their behavior to select a better
file for end users.


Overview
========

This PEP proposes the inclusion of a meta tag on the responses of every
successful request to a simple API page, which contains a name attribute
of "pypi:repository-version", and a content that is a :pep:`440` compatible
version number, which is further constrained to ONLY be Major.Minor, and
none of the additional features supported by :pep:`440`.

This would end up looking like::

  <meta name="pypi:repository-version" content="1.0">

When interpreting the repository version:

* Incrementing the major version is used to signal a backwards
  incompatible change such that existing clients would no longer be
  expected to be able to meaningfully use the API.
* Incrementing the minor version is used to signal a backwards
  compatible change such that existing clients would still be
  expected to be able to meaningfully use the API.

It is left up to the discretion of any future PEPs as to what
specifically constitutes a backwards incompatible vs compatible change
beyond the broad suggestion that existing clients will be able to
"meaningfully" continue to use the API, and can include adding,
modifying, or removing existing features.

It is expectation of this PEP that the major version will never be
incremented, and any future major API evolutions would utilize a
different mechanism for API evolution. However the major version
is included to disambiguate with future versions (e.g. a hypothetical
simple api v2 that lived at /v2/, but which would be confusing if the
repository-version was set to a version >= 2).

This PEP sets the current API version to "1.0", and expects that
future PEPs that further evolve the simple API will increment the
minor version number.


Clients
-------

Clients interacting with the simple API **SHOULD** introspect each
response for the repository version, and if that data does not exist
**MUST** assume that it is version 1.0.

When encountering a major version greater than expected, clients
**MUST** hard fail with an appropriate error message for the user.

When encountering a minor version greater than expected, clients
**SHOULD** warn users with an appropriate message.

Clients **MAY** still continue to use feature detection in order to
determine what features a repository uses.


Rejected Ideas
==============

Using a Header
--------------

Instead of baking this information into the actual HTML, an
alternative would be to use a HTTP header. This idea was
considered and ultimately was rejected because it would make
mirrors have to start modifying headers instead of being able
to operate as a "dumb" HTTP server of files.


Using an URL
------------

Another traditional mechanism for versioning APIs is to bake it
into the URL, something like ``/1.0/simple/`` or so. This works
well for major version changes where olders clients are not
expected to be capable of continuing to use it, but it is not
well suited to minor version bumps, particularly when the version
numbers can be viewed as largely advisory for end users.




Copyright
=========

This document is placed in the public domain or under the
CC0-1.0-Universal license, whichever is more permissive.



..
   Local Variables:
   mode: indented-text
   indent-tabs-mode: nil
   sentence-end-double-space: t
   fill-column: 70
   coding: utf-8
   End:
