2015-09-04 21:11:56 -04:00
|
|
|
|
PEP: 503
|
|
|
|
|
Title: Simple Repository API
|
|
|
|
|
Version: $Revision$
|
|
|
|
|
Last-Modified: $Date$
|
|
|
|
|
Author: Donald Stufft <donald@stufft.io>
|
|
|
|
|
BDFL-Delegate: Donald Stufft <donald@stufft.io>
|
|
|
|
|
Discussions-To: distutils-sig@python.org
|
2015-09-24 12:05:15 -04:00
|
|
|
|
Status: Accepted
|
2015-09-04 21:11:56 -04:00
|
|
|
|
Type: Informational
|
|
|
|
|
Content-Type: text/x-rst
|
|
|
|
|
Created: 04-Sep-2015
|
|
|
|
|
Post-History: 04-Sep-2015
|
2015-09-24 12:05:15 -04:00
|
|
|
|
Resolution: https://mail.python.org/pipermail/distutils-sig/2015-September/026899.html
|
2015-09-04 21:11:56 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Abstract
|
|
|
|
|
========
|
|
|
|
|
|
|
|
|
|
There are many implementations of a Python package repository and many tools
|
2015-09-05 12:11:45 -04:00
|
|
|
|
that consume them. Of these, the canonical implementation that defines what
|
2015-09-04 21:11:56 -04:00
|
|
|
|
the "simple" repository API looks like is the implementation that powers
|
|
|
|
|
PyPI. This document will specify that API, documenting what the correct
|
|
|
|
|
behavior for any implementation of the simple repository API.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Specification
|
|
|
|
|
=============
|
|
|
|
|
|
2019-05-09 17:27:53 -04:00
|
|
|
|
A repository that implements the simple API is defined by its base URL, this is
|
|
|
|
|
the top level URL that all additional URLs are below. The API is named the
|
|
|
|
|
"simple" repository due to the fact that PyPI's base URL is
|
|
|
|
|
``https://pypi.org/simple/``.
|
2015-09-04 21:11:56 -04:00
|
|
|
|
|
|
|
|
|
.. note:: All subsequent URLs in this document will be relative to this base
|
2019-10-11 07:15:25 -04:00
|
|
|
|
URL (so given PyPI's URL, a URL of ``/foo/`` would be
|
2019-05-09 17:27:53 -04:00
|
|
|
|
``https://pypi.org/simple/foo/``.
|
2015-09-04 21:11:56 -04:00
|
|
|
|
|
|
|
|
|
|
2020-03-03 13:19:37 -05:00
|
|
|
|
Within a repository, the root URL (``/`` for this PEP which represents the base
|
|
|
|
|
URL) **MUST** be a valid HTML5 page with a single anchor element per project in
|
|
|
|
|
the repository. The text of the anchor tag **MUST** be the name of
|
|
|
|
|
the project and the href attribute **MUST** link to the URL for that particular
|
|
|
|
|
project. As an example::
|
2015-09-04 21:11:56 -04:00
|
|
|
|
|
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html>
|
|
|
|
|
<body>
|
|
|
|
|
<a href="/frob/">frob</a>
|
|
|
|
|
<a href="/spamspamspam/">spamspamspam</a>
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|
|
|
|
|
|
|
|
|
|
Below the root URL is another URL for each individual project contained within
|
|
|
|
|
a repository. The format of this URL is ``/<project>/`` where the ``<project>``
|
|
|
|
|
is replaced by the normalized name for that project, so a project named
|
2019-10-11 07:15:25 -04:00
|
|
|
|
"HolyGrail" would have a URL like ``/holygrail/``. This URL must respond with
|
2015-09-04 21:11:56 -04:00
|
|
|
|
a valid HTML5 page with a single anchor element per file for the project. The
|
2019-10-11 07:15:25 -04:00
|
|
|
|
href attribute **MUST** be a URL that links to the location of the file for
|
|
|
|
|
download, and the text of the anchor tag **MUST** match the final path
|
|
|
|
|
component (the filename) of the URL. The URL **SHOULD** include a hash in the
|
|
|
|
|
form of a URL fragment with the following syntax: ``#<hashname>=<hashvalue>``,
|
|
|
|
|
where ``<hashname>`` is the lowercase name of the hash function (such as
|
|
|
|
|
``sha256``) and ``<hashvalue>`` is the hex encoded digest.
|
2015-09-04 21:11:56 -04:00
|
|
|
|
|
|
|
|
|
In addition to the above, the following constraints are placed on the API:
|
|
|
|
|
|
2015-09-05 12:11:45 -04:00
|
|
|
|
* All URLs which respond with an HTML5 page **MUST** end with a ``/`` and the
|
|
|
|
|
repository **SHOULD** redirect the URLs without a ``/`` to add a ``/`` to the
|
|
|
|
|
end.
|
|
|
|
|
|
|
|
|
|
* URLs may be either absolute or relative as long as they point to the correct
|
|
|
|
|
location.
|
2015-09-04 21:11:56 -04:00
|
|
|
|
|
2019-05-09 17:27:53 -04:00
|
|
|
|
* There are no constraints on where the files must be hosted relative to the
|
2015-09-04 21:11:56 -04:00
|
|
|
|
repository.
|
|
|
|
|
|
|
|
|
|
* There may be any other HTML elements on the API pages as long as the required
|
|
|
|
|
anchor elements exist.
|
|
|
|
|
|
2016-07-11 11:14:08 -04:00
|
|
|
|
* Repositories **MAY** redirect unnormalized URLs to the canonical normalized
|
2015-09-04 21:11:56 -04:00
|
|
|
|
URL (e.g. ``/Foobar/`` may redirect to ``/foobar/``), however clients
|
|
|
|
|
**MUST NOT** rely on this redirection and **MUST** request the normalized
|
|
|
|
|
URL.
|
|
|
|
|
|
|
|
|
|
* Repositories **SHOULD** choose a hash function from one of the ones
|
2015-09-05 12:11:45 -04:00
|
|
|
|
guaranteed to be available via the ``hashlib`` module in the Python standard
|
2015-09-04 21:11:56 -04:00
|
|
|
|
library (currently ``md5``, ``sha1``, ``sha224``, ``sha256``, ``sha384``,
|
|
|
|
|
``sha512``). The current recommendation is to use ``sha256``.
|
|
|
|
|
|
2015-09-05 12:11:45 -04:00
|
|
|
|
* If there is a GPG signature for a particular distribution file it **MUST**
|
|
|
|
|
live alongside that file with the same name with a ``.asc`` appended to it.
|
|
|
|
|
So if the file ``/packages/HolyGrail-1.0.tar.gz`` existed and had an
|
|
|
|
|
associated signature, the signature would be located at
|
|
|
|
|
``/packages/HolyGrail-1.0.tar.gz.asc``.
|
|
|
|
|
|
2015-09-24 12:01:20 -04:00
|
|
|
|
* A repository **MAY** include a ``data-gpg-sig`` attribute on a file link with
|
|
|
|
|
a value of either ``true`` or ``false`` to indicate whether or not there is a
|
|
|
|
|
GPG signature. Repositories that do this **SHOULD** include it on every link.
|
|
|
|
|
|
2016-07-22 12:44:43 -04:00
|
|
|
|
* A repository **MAY** include a ``data-requires-python`` attribute on a file
|
|
|
|
|
link. This exposes the *Requires-Python* metadata field, specified in PEP 345,
|
|
|
|
|
for the corresponding release. Where this is present, installer tools
|
|
|
|
|
**SHOULD** ignore the download when installing to a Python version that
|
|
|
|
|
doesn't satisfy the requirement. For example::
|
|
|
|
|
|
|
|
|
|
<a href="..." data-requires-python=">=3">...</a>
|
|
|
|
|
|
|
|
|
|
In the attribute value, < and > have to be HTML encoded as ``<`` and
|
|
|
|
|
``>``, respectively.
|
2015-09-04 21:11:56 -04:00
|
|
|
|
|
|
|
|
|
Normalized Names
|
|
|
|
|
----------------
|
|
|
|
|
|
|
|
|
|
This PEP references the concept of a "normalized" project name. As per PEP 426
|
|
|
|
|
the only valid characters in a name are the ASCII alphabet, ASCII numbers,
|
|
|
|
|
``.``, ``-``, and ``_``. The name should be lowercased with all runs of the
|
|
|
|
|
characters ``.``, ``-``, or ``_`` replaced with a single ``-`` character. This
|
|
|
|
|
can be implemented in Python with the ``re`` module::
|
|
|
|
|
|
|
|
|
|
import re
|
|
|
|
|
|
|
|
|
|
def normalize(name):
|
|
|
|
|
return re.sub(r"[-_.]+", "-", name).lower()
|
|
|
|
|
|
2016-07-22 12:44:43 -04:00
|
|
|
|
Changes
|
|
|
|
|
-------
|
|
|
|
|
|
|
|
|
|
* The optional ``data-requires-python`` attribute was added in July 2016.
|
|
|
|
|
|
2015-09-04 21:11:56 -04:00
|
|
|
|
|
|
|
|
|
Copyright
|
|
|
|
|
=========
|
|
|
|
|
|
|
|
|
|
This document has been placed in the public domain.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
..
|
|
|
|
|
Local Variables:
|
|
|
|
|
mode: indented-text
|
|
|
|
|
indent-tabs-mode: nil
|
|
|
|
|
sentence-end-double-space: t
|
|
|
|
|
fill-column: 70
|
|
|
|
|
coding: utf-8
|
|
|
|
|
End:
|