シンプルなリポジトリ API¶
この説明文書では、 "MUST" ・ "MUST NOT" ・ "REQUIRED" ・ "SHALL" ・ "SHALL NOT", ・ SHOULD" ・ "SHOULD NOT" ・ "RECOMMENDED" ・ "MAY" ・ "OPTIONAL"" を RFC 2119 で記述された意味に解釈します。
利用可能なパッケージバージョンを問い合わせたり、インデックスサーバからパッケージを取り出したりするためのインターフェースは、二つの形式: HTML と Jref:JSON によってもたらされます。
基本 API¶
シンプルな API を実装するリポジトリはベースとなる URL によって定義されます。これは、すべての追加的な URL 群がその下に連なるようなトップレベルの URL です。このような API は、 PyPI のベースとなる URL が https://pypi.org/simple/ であるという事実に即して、 "シンプル <simple>" リポジトリと名付けられます。
注釈
この説明文書でこのあと出てくる URL 群はすべて、このベース URL <base URL> からの相対的なものです (したがって、PyPI に関する URL なら、 /foo/ は https://pypi.org/simple/foo/ のことです。
正規化された名称¶
この仕様は、 "正規化された" プロジェクト名称の概念を参照しています。 名称正規化仕様 によれば、名称における正当な文字は、 ASCII アルファベット・ ASCII 数字・ . ・ - ・ _ だけです。名称は、 .` ・ - ・ _ がいくつ連続していてもそれを単一の - 文字に置き換え、小文字で統一されているべきです。これは Python の re モジュールで実装されています:
import re
def normalize(name):
return re.sub(r"[-_.]+", "-", name).lower()
PyPI のシンプルな API にバージョンを付与する¶
この仕様は、シンプルな API へのリクエストが成功するたびにそのレスポンスにメタタグを含めるように提案するもので、つまり、 pypi:repository-version という名称のアトリビューションを含み、その内容が バージョン指定子仕様 と互換性のあるバージョン番号であるが Major.Minor だけであるようにさらに制約されたものであって、 バージョン指定子仕様 でサポートされる追加的な機能を一つも含まないものです。
これは、結局こんなふうに見えることでしょう:
<meta name="pypi:repository-version" content="1.4">
リポジトリのバージョンを翻訳する時:
メジャーバージョンの増加は、既存のクライアントがその API を意味ある形で使うことができるとはもはや期待できないような後方互換性のない変更のシグナルとして使われます。
マイナーバージョンの増加は、既存のクライアントが依然として意味ある形で API を使うことができることが期待されるような、後方互換性を保つ変更のシグナルとして使われます。
将来の仕様の選択は、既存のクライアントが引き続き "意味ある形で" APIを使うことができるであろう、そして、既存の機能に対する追加・修正・削除ができるであろうという幅広い示唆を越えて、特に後方互換性の有無を構成するものに委ねられています。
メジャーバージョンを増加することは考えられず、将来発生する API の進化は API の進化における異なったメカニズムを通じて実現されるであろうというのが、この仕様の期待するところです。しかしながら、メジャーバージョンは、将来のバージョンとの違い (例えば、 /v2/ を使う仮説としてのシンプル API v2 、しかしこれはリポジトリバージョンが version >= 2 に設定されれば混乱を招くかもしれません) を明らかにするためにここに含まれているのです。
API バージョンの歴史¶
「—
API バージョン 1.0: API の初期バージョンで、 PEP 629 で宣言されたもの。
API バージョン 1.1: JSON シリアル化に
versions・files[].size・files[].upload-timeメタデータが追加されたもので、 PEP 700 で宣言されたもの。API バージョン 1.2: リポジトリに "tracks" メタデータを追加したもので、 PEP 708 で宣言されました。
API バージョン 1.3: PEP 740 で宣言されて、起源 <provenance> メタデータが追加されました。
API バージョン 1.4: PEP 792 で宣言されて、状態マーカが追加されました。
クライアント¶
シンプルな API と相互作用するクライアントは、応答を受け取るたびにそのリポジトリバージョンをよく 検査するべき で、もし存在しなければバージョン 1.0 であるものと 仮定しなければなりません 。
想定していたよりも大きなメジャーバージョンに遭遇した時には、クライアントは、ユーザ向けの適切なエラーメッセージと共に ハードフェイルをしなければなりません 。
想定していたよりも大きなマイナーバージョンに遭遇した時には、クライアントは、適切なメッセージと共にユーザに対して 警告するべき です。
クライアントは、リポジトリがどんな機能を使っているかを判断するために、さらに機能探索 <feature detection> を 継続しても構いません 。
HTML シリアル化¶
重要
The HTML representation is considered "frozen" and is not expected to be updated. Producers and consumers of the simple API should prefer the JSON representation.
See PEP 833 for additional information about the HTML representation's status.
後述の制約は、この仕様で記述されたすべての HTML シリアル化応答に適用されます:
HTML 応答はすべて、正当な HTML5 文書でなければ なりません 。
HTML 応答は、ひとつ以上の
metaタグを<head>セクションに含んでいても 構いません 。これらのタグのせマンティクスは、この後定義されます。
プロジェクトのリスト¶
リポジトリ内では、ルート URL <root URL> (この仕様ではベース URL <base URL> を表現する / のこと) は、正当な HTML5 ページであってリポジトリ内のプロジェクト毎にひとつのアンカー要素を持っていなければ なりません 。
アンカータグのテキストは、それぞれ、プロジェクトの名称でなければならず、 href アトリビュートはその特定のプロジェクトの URL にリンクされていなければ なりません 。例としては:
<!DOCTYPE html>
<html>
<body>
<a href="/frob/">frob</a>
<a href="/spamspamspam/">spamspamspam</a>
</body>
</html>
プロジェクトの詳細¶
以下のルート URL <root URL> は、リポジトリ内に含まれる個別の各プロジェクト向けのもうひとつの URL です。この URL のフォーマットは /<project>/ で、<project> は当該プロジェクトの正規化名称で置き換えられるものです。
Tip
例えば、 "HolyGrail" という名称のプロジェクトなら、 /holygrail/ のような URL を持つことでしょう。
プロジェクトの詳細 URL は、プロジェクトのファイル毎に単一のアンカー要素を伴った正当な HTML5 ページによって応答しなければなりません。 href アトリビュートはダウンロード用にそのファイルの所在地へリンクされた URL でなければ ならず 、アンカータグの文字列は URL の最後のパス構成要素 (ファイル名) でなければ なりません 。
各ファイル URL は、次のシンタックス: #<hashname>=<hashvalue> でハッシュ値を伴う形で URL フラグメントに含める べきで あり、ここで、 <hashname> は (sha256 のような) ハッシュ関数名を小文字で書いたもの、 <hashvalue> は 16 進数で表現されたダイジェストです。
上記に加えて、以下の制約が API に課せられます:
HTML5 ページで応答するすべての URL は
/で終わるものでなければならず、リポジトリは/で終わらない URL の最後に/を加えたものへリダイレクト するべき です。URL は、間違いのないロケーションを指し示している限りは絶対パスであっても相対パスであっても構いません。
ファイル群が置かれている場所が、リポジトリに対して相対的な場所のどこであるかについては制約条件はありません。
要求されているアンケー要素が存在している限り、API ページ上にどのような他の HTML 要素があっても構いません。
リポジトリは、正規化されていない URL を正統で正規化された URL にリダイレクトしても 構いません (例えば、
/Foobar/を/foobar/にリダイレクトしてもよい) が、クライアントの側ではこのリダイレクト機能に 依存してはならず 、正規化された URL に対してリクエストを 送らなければなりません 。レジストリは、 Python の標準ライブラリの
hashlibモジュール経由で利用可能であると保証されたハッシュ関数の中から一つを 選択するべきです (現時点では、md5・sha1・sha224・sha256・sha384・sha512)。現時点では、sha256の使用が推奨されています。特定の配布物ファイルに GPG 署名があれば、その配布物ファイルの名前に
.ascを追加したファイル名で 共存させなければなりません 。だから、/packages/HolyGrail-1.0.tar.gzが存在していて署名が結びついていれば、そのsと名は/packages/HolyGrail-1.0.tar.gz.ascという名前であるはずです。リポジトリは、ファイルへのリンクに
data-core-metadataアトリビュートを含めても 構いません 。リポジトリは、使用されたハッシュ関数の小文字での名称を
<hashname>とし、<hashvalue>を 16 進数表記のダイジェストであるものとした時、コアとなるメタデータのファイルのハッシュ値を<hashname>=<hashvalue>のシンタックスを使ったdata-core-metadataアトリビュートの値として提供する べきです 。リポジトリは、ハッシュ値が利用可能ではない時には、アトリビュートの値としてtrueを使っても 構いません 。リポジトリは、ファイルへのリンクに
data-dist-info-metadataアトリビュートを含めても 構いません 。インデックスクライアントは、もし存在していればこのキーを
data-core-metadataの伝統的なフォールバックとして消費しても 構いません 。リポジトリは、 GPG 署名が存在するか否かを示す
trueかfalseを値にとるdata-gpg-sigアトリビュートをファイルリンクの中に含んでいても 構いません 。これを行うリポジトリは、全てのリンクについて 行うべきです 。リポジトリは、ファイルリンクの中に
data-requires-pythonアトリビュートを含んでいても 構いません 。これは、対応するリリース用の Requires-Python メタデータを表示するものです。これが存在するなら、その要求を満足しないバージョンの Python 環境へインストールしている場合には、インストールツール群はダウンロードしたものを 無視するべき です。例えば:<a href="..." data-requires-python=">=3">...</a>
アトリビュートの値においては、 < や > は順に
<や>へと HTML エンコードされなければなりません。リポジトリは、ファイルリンクに
data-yankedアトリビュートを含めても 構いません 。data-yankedアトリビュートは、値をとらなくても構いませんし、任意の文字列を値に取っても構いません。data-yankedアトリビュートが存在していれば、この特定のリンクによって指し示されたファイルが "ヤンクされた <Yanked>" ものだと解釈される べきであって 、特定のシナリオ下を除けば一般的にはインストーラによって選択されるべきものではありません。data-yankedアトリビュートの値は、もし値が存在するなら、そのファイルがヤンクされた理由を表現する任意の文字列です。注釈
ツール類がヤンクされたファイルをどのように扱うべきかのセマンティクスは、 ファイルのヤンク <Yanking> に記述されています。
リポジトリは、ファイルリンクに
data-provenanceアトリビュートを含めても 構いません 。このアトリビュートの値は、その URL で当該ファイルの起源が見つかることを合図しつつ、完全に指定された URL でなければ なりません 。この URL は、 セキュアな起源 を表現していなければ なりません 。注釈
data-provenanceアトリビュートは、 API バージョン 1.3 で追加されました。注釈
リンクされた起源のフォーマットは、 インデックスにホストされた証明 <Index hosted attestations> で定義されています。
リポジトリは、
pypi:project-statusとpypi:project-status-reasonのメタタグを応答そのものに含めても 構いません 。もし存在すれば
pypi:project-status-reasonの値は任意の文字列でなければ ならない 一方で、pypi:project-statusの値は正当なプロジェクト状態マーカでなければ なりません 。注釈
正当なプロジェクト状態マーカとそのセマンティクスの組は、 プロジェクトステータスのマーカ群 に記述されています。
注釈
pypi:project-statusとpypi:project-status-reasonのメタタグは、 API バージョン 1.4 で追加されました。
シンプルな API で配布物のメタデータを提供する¶
簡明なリポジトリのプロジェクトページでは、配布物を指し示すアンカータグは、それぞれ、 data-dist-info-metadata アトリビュートを 持っていても構いません 。このアトリビュートが存在していることで、そのアンカータグが提示する配布物が、その配布物が処理されたりインストールされたりしても変更されないであろうコアとなるメタデータのファイルを 持っていなければならない ことを示します。
もし data-dist-info-metadata アトリビュートが存在するなら、リポジトリは、配布物の名称に .metadata を追加したファイル名で配布物のコアとなるメタデータのファイルを配布物と共に 提供しなければなりません 。例えば、 /files/distribution-1.0-py3.none.any.whl が提供されている場所で提供される配布物のコアとなるメタデータは、 /files/distribution-1.0-py3.none.any.whl.metadata という場所に置かれることになるでしょう。これは、 基本となる HTML API の仕様 で GPG 署名のファイルの場所の指定するやり方と似ています。
リポジトリは、 <hashname> がハッシュ関数の小文字で書いた名称で hashvalue が16進数に符号化されたハッシュ値であるとして <hashname>=<hashvalue> という書式を使って、 data-dist-info-metadata アトリビュートの値としてコアとなるメタデータのファイルのハッシュ値を 提供するべきです 。ハッシュ値を利用できない場合には、リポジトリはアトリビュートの値として true を 使っても構いません 。
後方互換性¶
アンカータグに data-sidt-info-metadata アトリビュートがない場合、ツール群は、配布物をダウンロードするというその時点の動作を反転して、メタデータを調べるという動作に変更することが期待されています。
新しい data-dist-info-metadata アトリビュートをサポートしてない古めのツール群は、このアトリビュートを無視することを期待されており、メタデータを検査するために配布物をダウンロードするという現在の動作を維持することを期待されています。これは、先の data- アトリビュート追加の際に、既存のツール群が期待された動作と似ています。
Python パッケージインデックス向けのJSON ベースのシンプルな API¶
標準ライブラリのみを使うレスポンス解析を有効にするためには、この仕様では、 (ファイル群それ自体と 基本となる HTML API の仕様 を別にして) すべてのレスポンスが JSON を用いてシリアライズされているべきであると指定しています。
ゼロコンフィグレーションディスカバリを有効にして追加的な HTTP リクエストの量を最小化するために、この仕様では HTML:ref:基本となる HTML API の仕様 を拡張して、 (ファイル群それ自体を除く) すべての API エンドポイントが HTTP コンテンツネゴシエーションを使ってクライアントおよびサーバが提供するべき正しいシリアライズのフォーマット、即ち HTML もしくは JSON を選択できるようにしています。
バージョニング¶
バージョン付与については、 API のバージョン付与に関する仕様 のフォーマット (Major.Minor) を固守していて、既存の HTML レスポンスについては 1.0 と定義されています。この仕様では API に新しい機能を持ち込むことはせず、むしろ、既存の機能のための異なるシリアル化フォーマットを記述しようとしているので、この仕様が既存の 1.0 バージョンに変更を加えることはなく、代わりにどのようにして JSON にシリアライズするのかを述べるに留めています。
API のバージョン付与に関する仕様 と同様に、既存のクライアントが意味のある形でそのフォーマットを理解することをもはや期待できないようになる新しいフォーマットをもたらすような変更があった場合には、メジャーバージョン番号を 増加させなければなりません 。
同様に、マイナーバージョンは、そのフォーマットで機能の追加・削除はあっても既存のクライアントが意味ある形でそのフォーマットを理解できる状態が継続すると期待されるであろうという時に限って 増加されなければなりません 。
既存のクライアントがそのフォーマットを意味ある形で理解することができないという結果に陥らないような、かつ、機能の追加や削除に相当しないような変更は、バージョン番号の変更を伴わずに行っても構いません。
これは意図的に曖昧にされています、というのは、この仕様では、メジャーバージョンなりマイナーバージョンなりを増加するべきか否かを考究し決定するべき API での変更をもたらすような将来の仕様に、余地を残すことが最善であると信じられているからです。
API の将来のバージョンでは、そのバージョンで利用可能なシリアル化のサブセットでのみ実現させることができるような何かを追加しても構いません。あらゆるシリアル化のバージョン番号は、メジャーバージョンにおいては、 同期を保つべき ですが、ある機能がそれぞれのフォーマットにシリアル化されるやり方の詳細は、その機能が存在するかしないかを含めて、異なっていても構いません。
この仕様の意図するところは、API はデータを返す URL エンドポイントであって、その解釈は当該データのバージョンによって定義され、その後にターゲットとなるシリアル化フォーマットにシリアライズされるものであると考えられるべきであるということです。
JSON シリアル化¶
基本となる HTML API の仕様 からの URL の構造は依然として適用されます、というのは、この仕様は既に存在する API にシリアル化フォーマットを付け足すだけだからです。
後述の制約は、この仕様で記述されたすべての JSON シリアル化応答に適用されます:
すべての JSON 応答は、配列やその他の型ではなく 常に JSON オブジェクトであることでしょう。
JSON は URL 型をネイティブにサポートしているわけではない一方で、この API における任意の値で URL を表現するようなものは、それが正しい場所を指し示している限り絶対パスであっても相対パスであっても構いません。相対パスの場合には、恰も HTML であるかのように、現在の URL に対する相対パスになっています。
API 応答の中の任意の辞書オブジェクトに追加的なキー群を追加しても構いませんし、クライアントは自身が理解しないキー群については 無視しなければなりません 。
あらゆる JSON 応答は、その応答の内容ではなく応答それ自身に関係する情報を含む
metaキーを持つことでしょう。すべての JSON 応答は、 API のバージョン付与に関する仕様 で定義されたものと同じ失敗/警告のセマンティクスを持ち、かつ、 API のバージョン付与に関する仕様 の
Major.Minorの形のバージョン番号を文字列として値に取るようなmeta.api-versionキーを持つことでしょう。基本となる HTML API の仕様 のすべての要求事項のうちの HTML に特化したもの以外は、依然として適用されます。
(どのレベルでも) 先頭にアンダースコアを伴うキーは、インデックスサーバが使うプライベートなものとして予約されています。将来の標準において、このようなキーに意味を付与することはありません。
プロジェクトのリスト¶
(ベース URL <base URL> を表現する) この仕様でのルート URL <root URL> / は、 JSON にエンコードされた辞書であって、二つのキーを持つでしょう:
projects: 各エントリがディレクトリで単独のキーnameを持つような配列で、(そのキーの値は) プロジェクトの名称を表す文字列です。meta: 先述の通り の一般的な応答メタデータ。
ひとつの例として:
{
"meta": {
"api-version": "1.4"
},
"projects": [
{"name": "Frob"},
{"name": "spamspamspam"}
]
}
注釈
name フィールドは、基本となる HTML API の仕様 からのものと同じで、正規化していないディスプレイ用名称であるのか正規化済みの名称であるのかを指定していません。実際には、これらの仕様の相異なる実装において異なる選択を行うことがあり、その選択によって非正規化名称か正規化名称かは当該リポジトリの実装の詳細に依存します。
注釈
projects キーは配列なので何らかの種類の順序が要求されますが、 基本となる HTML API の仕様 もこの仕様も特定の順序に並べることを要求しておらず、また、あるリクエストと次のものとで順序が変わらないことも要求していません。心情としては、これが (配列ではなく) 集合であると考えるのが最適ですが、 JSON も HTML も集合を扱う機能を欠いています。
プロジェクトの詳細¶
この URL のフォーマットは /<project>/ で、 <project> の部分は 基本となる HTML API の仕様 にしたがって正規化されたプロジェクト名称であり、したがって、 "Silly_Walk" という名称のプロジェクトであれば /silly-walk/ のような URL を持つことになるでしょう。
この URL は、5個のキーを持つJSON にコード化された辞書を返さなければなりません:
name: そのプロジェクトの正規化された名前。project-status: オプションの辞書で、次のものを内包する:status: もし存在すれば、これは、正当なプロジェクト状態マーカで なければなりません 。注釈
正当なプロジェクト状態マーカとそのセマンティクスの組は、 プロジェクトステータスのマーカ群 に記述されています。
注釈
statusキーは、 API バージョン 1.4 で追加されました。reason: もし存在すれば、これは、任意の文字列でプロジェクトの状態を記述するもので なければなりません 。注釈
reasonキーは、 API バージョン 1.4 で追加されました。
注釈
project -statusキーは、 API バージョン 1.4 で追加されました。files: 辞書のリストで、各辞書が個別のファイルを表現しているもの。meta: 先述の通り の一般的な応答メタデータ。versions: バージョン番号文字列のリストで、このプロジェクトのためにアップロードされたプロジェクトのバージョン番号を全て指定するもの。versionの値は、論理上は集合であり、それ故に重複を許さず、バージョン番号の順序は大きな問題ではありません。注釈
filesキーに列挙されたファイルは、すべて、versionsキー内のバージョンのひとつに対応していなければなりません。versionsキーは、 (サーバ側がそのような概念を持っているならば、ファイルなしのバージョンというものを表現するために) 対応するファイルがないバージョンを含んでいても構いません。注釈
バージョン指定子仕様 (VSS) の採用前からの "レガシー" データをサーバが保持しているかもしれないので、バージョン文字列について VSS に則ったバージョンであることを要求することはできませんし、したがって、 VSS のルールを使って並べることができると仮定することもできません。しかしながら、サーバ側は、可能であれば正規化された VSS バージョンを 使うべきです 。
注釈
versionキーは、 API バージョン 1.1 で追加されました。
個別のファイルを表す辞書は、それぞれ、次のキーを持ちます:
filename: 表現しようとしているファイルのファイル名。url: そこからそのファイルを取得できる URL。hashes: ハッシュ(関数)の名称と、そのファイルの16進数にエンコードされたハッシュ値 (digest) をマッピングした辞書。複数のハッシュを含むことが可能で、その複数のハッシュを使って何をするのか (全部について検証するのか、サブセットについてなのか、全く何もしないのか) についてはクライアントが決めれば良いことになっています。これらのハッシュの名称は、常に小文字に 正規化 されているべきです 。hashes辞書は、仮にそのファイルについてハッシュがひとつも利用可能でないとしても、 存在していなければなりません し、少なくともひとつのセキュアで利用可能であることが保証されているハッシュが常に含まれていることが とても強く 推奨されています。デフォルトでは、
hashlibを経由して利用可能なハッシュアルゴリズム (特に、hashlib.new()に渡すことができて、かつ、追加のパラメータを要求しないもの) は、すべて、ハッシュの辞書のキーとして使うことができます。 :py:`data:`hashlib.algorithms_guaranteed` から選択した少なくともひとつのセキュアなアルゴリズムが、常に、 含まれているべきです 。この仕様の時点では、特にsha256が推奨されます。requires-python: Requires-Python メタデータフィールドを顕にする オプションの キー。これが存在しているなら、インストーラツール群は、要求事項を満足しない Python のバージョンへインストールしようとする場合、ダウンロードを 無視するべきです 。基本となる HTML API の仕様 の中の
data-requires-pythonとは異なって、requires-pythonキーは、JSON が自然に要求することを除けば、特別なエスケープを要求しません。core-metadata: API メタデータの仕様 で指定されたのと同じ場所 ({file_url}.metadata) を通じて当該ファイルに関するメタデータが利用可能であることを示す**オプション** のキー。これが存在する場合には、そのファイルに対応するメタデータファイルがあるか否かを示すブーリアンであるか、または、ハッシュ名称からメタデータのハッシュを16進数にエンコードしたダイジェストへの対応をマッピングする辞書であるか、のいずれかで なければなりません 。これがブーリアンの代わりにハッシュ辞書である時には、
hashesキーが true を値に取る場合と同じ要求事項と推奨事項の全てが、このキーにも課されます。このキーがない場合には、メタデータファイルが存在するかもしれませんし、存在しないかもしれません。このキーの値が真である場合はメタデータファイルが存在し、値が偽の場合には存在しません。
サーバ群は、可能であれば、メタデータファイルのハッシュを利用可能とすることが推奨されています。
dist-info-metadata: オプション で、core-metadataの非推奨になった別名。インデックスのクライアントは、もしこのキーが存在すれば、
core-metadataのレガシーなフォールバック先として、このキーを 消費しても構いません 。gig-sig: オプション のキーで、当該ファイルに GPG 署名が付属しているか否かを示すブーリアン。署名ファイルへの URL は、 基本となる HTML API の仕様 で指定されたもの ({file_url}.asc) に従います。このキーが存在しない場合は、署名はあるかもしれませんし、ないかもしれません。yanked: オプション のキーで、当該ファイルがヤンクされたものか否かを示すブーリアンか、または、ファイルがヤンクされるに至った特定の理由を示す任意の空ではない文字列か、のいずれかの値を持ちます。yankedキーが存在して値が真のようであれば、urlフィールドによって指し示されるファイルが "ヤンク" されたことを示すものと 理解されるべきです 。注釈
ツール類がヤンクされたファイルをどのように扱うべきかのセマンティクスは、 ファイルのヤンク <Yanking> に記述されています。
size: 必須の キー。ファイルサイズをバイト単位で表した整数が 含まれていなければなりません 。注釈
sizeキーは、 API バージョン 1.1 で追加されました。upload-time: オプションの キーで、もし存在するなら、当該ファイルがインデックスへアップロードされた時刻を表現する正当な ISO 8601 の年月日/時分秒の文字列がyyyy-mm-ddThh:mm:ss.ffffffZの書式で 含まれていなければなりません 。後置された
Zが示すように、アップロード日時は必ず UTC タイムゾーンを 使わなければなりません 。タイムスタンプの秒に満たない部分 (.ffffffの部分) はオプションで、もし存在するなら6桁までの精度を含めて構いません。サーバ側がファイルのアップロード日時を記録していない場合は、upload-timeキーを 省略しても構いません 。注釈
upload-timeキーは、 API バージョン 1.1 で追加されました。prevenance: オプションの キーで、もし存在するなら JSON 文字列か、または、nullのいずれかで なければなりません 。もしnullでないならば、 基本となる HTML API の仕様 内のdata-provenanceと同様のルールで、ファイルに関連する起源への URL で なければなりません 。注釈
provenanceフィールドは、 API バージョン 1.3 で追加されました。
ひとつの例として:
{
"meta": {
"api-version": "1.4",
"project-status": "active",
"project-status-reason": "this project is not yet haunted"
},
"name": "holygrail",
"files": [
{
"filename": "holygrail-1.0.tar.gz",
"url": "https://example.com/files/holygrail-1.0.tar.gz",
"hashes": {"sha256": "...", "blake2b": "..."},
"requires-python": ">=3.7",
"yanked": "Had a vulnerability",
"size": 123456
},
{
"filename": "holygrail-1.0-py3-none-any.whl",
"url": "https://example.com/files/holygrail-1.0-py3-none-any.whl",
"hashes": {"sha256": "...", "blake2b": "..."},
"requires-python": ">=3.7",
"dist-info-metadata": true,
"provenance": "https://example.com/files/holygrail-1.0-py3-none-any.whl.provenance",
"size": 1337
}
],
"versions": ["1.0"]
}
注釈
files キーは配列なのである種の順序があることが要求される一方で、 基本となる HTML API の仕様 にもこの仕様にも、特定の順序付けも要求されていませんし、あるリクエストと次のそれの間で順序が保たれるということも要求されていません。心情としては、これは集合であると考えるのが最適ですが、JSON にも HTML にも集合を扱う機能は欠落しています。
Content-Types¶
この仕様では、シンプル API からの応答はすべて、その応答が何であるか (シンプル API からの応答である) 、どのバージョンの API を表現しているか、また、使われているシリアル化フォーマットは何であるかを記述する標準のコンテント型を持ちます。
このコンテント型の構造はこのようになっていることでしょう:
application/vnd.pypi.simple.$version+format
これらの API からの応答のうちのひとつをクライアントが理解しようと試みる際には、メジャーバージョンだけが継続不可能にするものであるべきなので、メジャーバージョンだけがコンテント型に含まれるでしょうし、それがバージョン番号であることを明確にするために前に v をつけられることになるでしょう。
ということは、既存の 1.0 API においては、コンテント型はこのようになるでしょう:
JSON:
application/vnd.pypi.simple.v1+jsonHTML:
application/vnd.pypi.simple.v1+html
上記に加えて、特別な "meta" バージョンが latest という名前でサポートされており、その目的はクライアントが完全に最新のバージョンをリクエストすることを許すためであり、そのバージョンが何であるかを前もって知ることを不要にするためです。しかしながら、クライアントは自身がどのバージョンをサポートしているのかを明示的に示すことが推奨されています。
既存の 基本となる HTML API の仕様 の API 応答が text/html コンテント型を使うことを期待している既存のクライアント群をサポートするために、この仕様では、さらに、 text/html を application/vnd.pypi.simple.v1+html コンテント型へのエイリアスであると定義しています。
バージョン + フォーマットの選択¶
今や複数の可能なシリアル化が存在するので、クライアント群がどのシリアル化フォーマットであれば理解できるのかを示すことができるようにする必要があります。加えて、以前の API バージョンを期待している既存のクライアント群の妨げとなることなしに、どんな API の可能な新しいメジャーバージョンでも追加することができれば利益があることでしょう。
これを可能にするために、この仕様では、 HTTP の サーバ主導のコンテントネゴシエーション の使用を標準化します。
この仕様では、サーバ主導のコンテントネゴシエーションについて完全にすべてを記述することはありませんが、流れは大まかに次のようになります:
理解できるコンテント型を全て``Accept`` ヘッダに列挙した HTTP リクエストをクライアントが作成します。
サーバはそのヘッダを検証して、列挙されたコンテント型からひとつを選択して、そのコンテント型を使って応答を返します (
Acceptヘッダが欠落している場合はAccept: */*であるものとして扱います) 。Acceptヘッダにあるコンテント型のいずれもサーバがサポートしていない場合には、どのように応答するかについてサーバは3個の異なるオプションから選択することができます:クライアントが要求したものではないデフォルトのコンテント型を選択して、それを使って応答を返すこと。
HTTP の
406 Not Acceptable応答を返すことで、要求されたコンテント型の中に利用可能なものがないことを示し、サーバとしてはデフォルトのコンテント型を選択して応答することができないかしたくないことを示すこと。HTTP の
300 Multiple Choices応答を返して、選択できるかもしれないすべての可能な応答のリストを含めておくこと。
サーバが返すかもしれない異なる応答のタイプを取り扱ってクライアントは応答を解釈します。
この仕様は、あるコンテント型を取り扱うことについてサーバが行った選択のどれが (クライアントへ応答を) 返すことができないものであるかを指定しませんし、クライアント側がそのクライアントにとって最も意味を為す方法であればどんなものでも可能な応答の全てを取り扱う準備を しておくべきだ とは指定しません。
しかしながら、 300 Multiple Choices 応答がどのように解釈され得るかについて標準的なフォーマットは存在しないので、クライアント側が理解して要求するべき別のコンテント型を選択する手段がないので、この仕様ではサーバがこのオプションを採用することを強い非推奨にしています。加えて、クライアントが別のコンテント型を 理解できるであろう とは思われず、したがって、この応答は 406 Not Acceptable エラーと同じ扱いを受けるのが精々であろうと思われます。
この仕様では、メタバージョン latest が使われているのであれば、そのサーバは、実際のバージョンのための Content-Type をレスポンスの中に 伴わなければならない ということを 要求しています (すなわち、 Accept: application/vnd.pypi.simple.latest+json を含んだリクエストが v1.x を返す時、レスポンスには application/vnd.pypi.simple.v1+json を値とする Content-Type が入っていなければならないということです) 。
Accept ヘッダは、クライアントが理解し処理することが可能なコンテント型をカンマで区切られたリストに列挙したものです。まさに要求されているところのコンテント型のそれぞれについて3個の異なるフォーマットをサポートしています:
$type/$subtype$type/**/*
バージョン+フォーマット <version+format> の選択に使うには、これらのうちで最も役に立つのは $type/$subtype で、望みのバージョンとフォーマットを実際に指定する唯一の方法だからです。
Accept ヘッダに列挙されたコンテント型の順序は、なんら特定の意味を持たず、サーバ側ではその全てをそれを使って応答するために等しく正当なものと 考えるべきです 。クライアント側が特定のコンテント型を他のものよりも好むことを指定したいならば、 Accept ヘッダの quality バリュー の文法を使っても構いません。
これは、 ;q= とこれに後続する10進数で3桁までの 0 以上 1 以下の値を付加することによって Accept ヘッダ内の特定のエントリの優先度をクライアントが指定することを可能にします。この値を解釈する際には、より高い q 値 (quality 値) のエントリがより低い品質のものよりも優先され、q 値を持たないものはデフォルトで 1 であると解釈されます。
しかしながら、サーバはクライアント側から要請されたコンテント型の どれ を選んでも構わないということ、そして、サーバはクライアントが 要請しなかった コンテント型で返答しても構わないということを、クライアントは心に留めておくべきです。
API へのリクエストから受けとった応答のコンテント型を決定するにあたってクライアントを補助するために、この仕様では、応答のコンテント型を示す Content-Type ヘッダをサーバが常に含めることを要求している。これは、技術的には後方互換性のない変更ですが、実際には pip ` はすでにこの要求事項 を強制していますので、実際に何かを壊すリスクは低いでしょう。
クライアントがどのように運用できるかの例は次のように見えるでしょう:
import email.message
import requests
def parse_content_type(header: str) -> str:
m = email.message.Message()
m["content-type"] = header
return m.get_content_type()
# Construct our list of acceptable content types, we want to prefer
# that we get a v1 response serialized using JSON, however we also
# can support a v1 response serialized using HTML. For compatibility
# we also request text/html, but we prefer it least of all since we
# don't know if it's actually a Simple API response, or just some
# random HTML page that we've gotten due to a misconfiguration.
CONTENT_TYPES = [
"application/vnd.pypi.simple.v1+json",
"application/vnd.pypi.simple.v1+html;q=0.2",
"text/html;q=0.01", # For legacy compatibility
]
ACCEPT = ", ".join(CONTENT_TYPES)
# Actually make our request to the API, requesting all of the content
# types that we find acceptable, and letting the server select one of
# them out of the list.
resp = requests.get("https://pypi.org/simple/", headers={"Accept": ACCEPT})
# If the server does not support any of the content types you requested,
# AND it has chosen to return a HTTP 406 error instead of a default
# response then this will raise an exception for the 406 error.
resp.raise_for_status()
# Determine what kind of response we've gotten to ensure that it is one
# that we can support, and if it is, dispatch to a function that will
# understand how to interpret that particular version+serialization. If
# we don't understand the content type we've gotten, then we'll raise
# an exception.
content_type = parse_content_type(resp.headers.get("content-type", ""))
match content_type:
case "application/vnd.pypi.simple.v1+json":
handle_v1_json(resp)
case "application/vnd.pypi.simple.v1+html" | "text/html":
handle_v1_html(resp)
case _:
raise Exception(f"Unknown content type: {content_type}")
クライアント側が、 HTML だけを、または JSON だけをサポートしたいと望むなら、 Accept ヘッダから望まないコンテント型を単に取り除くでしょうし、(望まないものを) 受け取ったらエラーにすることでしょう。
代わりの交渉機構 <Negotiation Mechanisms>¶
HTTP でのコンテンツネゴシエーションを使うことがクライアントとサーバが協調してクライアントが理解することができる HTTP 応答を得られることを確実にする標準的な方法である一方で、このメカニズムで十分とは言えないような状況が存在します。そのような場合向けに、この仕様には、 オプションとして 代わりに使っても構わない代わりの交渉機構 <alternative negotiation mechanisms> があります。
URL パラメータ¶
シンプル API を実装するサーバは、クライアントが URL の特定のバージョンを要求することを許すために、 format という名称の URL パラメータをサポートすることを選択しても構いません。
format パラメータの値は、正当なコンテント型のうちの ひとつ であるべきです。複数のコンテント型を渡すことやワイルドカード、quality 値などはサポートされて いません 。
このパラメータをサポートすることはオプションで、 API とやりとりするクライアントはこれを 当てにするべきではありません 。このネゴシエーションメカニズムは、人間がブラウザ内で API をより簡単に調査することができるようにすることを意図したもの、ないし、説明文書やノートから特定の version+format にリンクすることができるようにすることを意図したものです。
このパラメータをサポートしないサーバの側では、これの存在時にはエラーを返すことを選択しても構いませんし、単にその存在を無視しても構いません。
サーバがこのパラメータを実装していない時は、クライアントの Accept ヘッダ内の値に何があってもそれに 高い優先度を与えるべき で、要求されたフォーマットをサーバがサポートしていないなら Accept ヘッダにフォールバックすることを選択しても良いし、標準的なサーバ側が駆動するコンテントネゴシエーションが典型的に持っているエラーコンディション (例えば、 406 Not Available や 303 Multiple Choices 、ないし、応答のデフォルトの型) のどれでもひとつを選択しても構いません。
エンドポイントの設定¶
このオプションは、技術的には何ら特別なオプションではなく、コンテントネゴシエーションを使用することに伴う自然な結果であり、利用可能なコンテント型のいずれかを自身のデフォルトとしてサーバが選択することを許すものです。
あるサーバがサーバ主導のコンテントネゴシエーションを実装したくないか実装することができなくて、むしろユーザに対してクライアントが望むバージョンを選択するように明示的に要求するのであれば、それはサポートされているコンフィグレーションのひとつです。
これを有効にするためには、サーバは、複数のエンドポイント (例えば、 /simple/v1+html/ と /simple/v1+json/ のいずれかまたは両方) をサポートしたいと考える version+format のそれぞれにするべきです。このようなエンドポイントのもとでは、コンテント型のひとつ (またはサブセット) をサポートするリポジトリのコピーをホストすることができます。クライアントが Accept ヘッダを使ってリクエストした時に、サーバはそれを無視して当該エンドポイントに対応するコンテント型を返すことができます。
特定のコンフィグレーションを要求したいと願うクライアントにとっては、ある特定のリポジトリ URL にどんな version+format が設定されたかを追跡することができますし、そのサーバへのリクエストを作成する時に正しいコンテント型 だけ を含んだ Accept ヘッダを発出することができます。
推奨事項¶
この節は 規範的ではなく、この仕様を実装する上での最善のデフォルト実装の決定だと仕様の執筆者たちが信じるものを表現していますが、しかし、これらの決定に合致させるための要求事項としてはいかなるものも 表現していません 。
これらの決断は、 API の最新のバージョンの上に移行できるような、その一方でなるべく大量の互換性も維持するような要求事項を数の上でなるべく最大化するように選択されています。加えて、クライアント側が最善の選択を行うようにと試みるガードレールを API が提供するように試みてきました。
サーバには次のことが推奨されます:
サーバ主導のコンテントネゴシエーションを使って、合理的に可能である限り、もしくは、少なくとも HTML 応答を用いる非自明のトラフィックを受け取る限り、この仕様の中で記述される3個のコンテント型の全てをサポートすること。
サーバは、どのように協働すれば良いかを知っているコンテント型をひとつも含まないような
Acceptヘッダに遭遇した時、300 Multiple Choice応答を返すべきではなく、その代わりに406 Not Acceptable応答を返すべきです。しかしながら、このエンドポイント設定を使うことを選択したなら、 できることならそのエンドポイントが期待しているコンテント型で
200 Okを返したいと考えるべきです。
受け入れ可能なバージョンを選択する時、サーバは、クライアントがサポートする中で、最も表現力が豊かで機能的なシリアル化フォーマットを伴っていて、クライアント側が表現したクオリティ優先度 <quality priority> と同じくクライアントからのリクエストの特質を考慮に入れて、最も高いバージョンを選択するべきであり、
text/htmlコンテント型の使用は最後の逃避先とするべきです。
クライアント側には次のことが推奨されます:
それが合理的に実行可能である限り、サーバ側が駆動するコンテンツネゴシエーションを使ってこの仕様に記述された3個のコンテント型の全てをサポートすること。
Acceptヘッダを構築する時、サポートしているコンテント型の全てを含めること。サーバ側で考慮に入れてもらいたい特定の理由 (例えば、標準ライブラリの HTML パーサを使っていて、何らかのエッジケースにおいてパースできない何らかの種類の HTML 応答があるかもしれないと心配している場合) のある実装でない限り、一般的にコンテント型にはクオリティ優先度 <quality priority> を含めるべきではありません。
この推奨事項に対する例外のひとつは、それがリクエストしている唯一のコンテント型であるという場合を除けば、伝統的な
text/htmlコンテント型には;q=0.01を含めることが推奨されるということです。通常操作では
latestメタバージョンを使うのではなくて、希求しているバージョンがどれであるかを明示的に選択すること。応答の
Content-Typeを調べて、こちらが期待しているものに合致していることを確認すること。
歴史¶
2015年9月: PEP 503 で HTML フォーマットの初期フォーム
2016年7月: PEP 503 で Requires-Python メタデータ
2019年5月: PEP 592 で "ヤンク <yank>" サポート
2020年7月: PEP 629 で、 API バージョン付け慣行とメタデータ、 HTML フォーマットを API v1.として宣言
2021年5月: PEP 658 で、パッケージとは独立にパッケージのメタデータを提供
2022年5月: PEP 691 により、クライアント側が選択する機構とともに JSON フォーマットの初期の形、両フォーマットを API v1 として宣言
2022年10月: PEP 700 により、 JSON フォーマットにおけるプロジェクトバージョン・ファイルサイズ・アップロード日時
2023年6月: PEP 714 により、パッケージから独立したパッケージメタデータを提供するフィールドを名称変更
2024年11月: PEP 740 によって、 HTML フォーマットおよびJSON フォーマットにおける起源 <provenance> メタデータ
2025年7月: PEP 792 によって、HTML フォーマットおよび JSON フォーマットにおけるプロジェクトの状態マーカ
2025年7月: レイアウトの変更 (ファイルのヤンクのための専用のページ、 API の詳細の前に概念を紹介)
June 2026: PEP 833 formally "freezes" the HTML representation of the simple API