PEP 621 – pyproject.toml にプロジェクトメタデータを保存する
- Author:
- Brett Cannon <brett at python.org>, Dustin Ingram <di at python.org>, Paul Ganssle <paul at ganssle.io>, Pradyun Gedam <pradyunsg at gmail.com>, Sébastien Eustace <sebastien at eustace.io>, Thomas Kluyver <thomas at kluyver.me.uk>, Tzu-ping Chung <uranusjr at gmail.com>
- Discussions-To:
- Discourse thread
- Status:
- Final
- Type:
- Standards Track
- Topic:
- Packaging
- Created:
- 22-Jun-2020
- Post-History:
- 22-Jun-2020, 18-Oct-2020, 24-Oct-2020, 31-Oct-2020
- Resolution:
- Discourse message
Table of Contents
- 概要
- 動機
- 根拠
- 仕様
- 後方互換性
- セキュリティの影響
- 参考実装
- 却下されたアイデア
- 他のテーブル名
- メタデータプロバイダーのサポート
- 正規化されたプロジェクト名を要求する
- ビルド時に含めるファイルを指定する
[project.urls]テーブルを[project.project-urls]と命名する- 別の
url/home-pageフィールドを持つ - ツールが開発関連の依存関係を「dev」エクストラに配置することを推奨する
dynamicフィールドが欠落している必須フィールドのみを指定することを要求するreadmeフィールドの異なる構造readmeフィールドがtext/plainを暗示することを許可するdependencies/optional-dependenciesの他の名前authorsとmaintainersを統一してauthorsにするproject.entry-pointsのテーブルの任意の深さをサポートする- 依存関係を指定するために構造化された TOML 辞書を使用する
- ビルドバックエンドが sdist を生成する際に
pyproject.tomlを更新することを要求する - ツールがデータを追加/拡張することを許可する
- 未解決の問題
- 著作権
概要
この PEP は、パッケージ関連ツールが消費するためのプロジェクトの コアメタデータ を pyproject.toml ファイルに書き込む方法を指定します。
動機
この PEP の主な動機は次のとおりです:
- ユーザーがビルドバックエンドによって静的にメタデータを指定することを奨励し、速度、指定の容易さ、曖昧さの排除、および決定論的な消費を実現する
- ビルドバックエンド間での学習と移行の容易さのために、ツールに依存しない方法でメタデータを指定する
- プロジェクトのメタデータの「退屈な部分」を共有するために、ビルドバックエンド間でのコード共有を促進する
静的メタデータの指定の動機について具体的に言えば、それはパッケージングエコシステムの全体的な目標です。そのため、メタデータを静的に指定することを容易にすることが重要です。これにより、メタデータを動的に指定するコストを上げることも許容されます。ユーザーは静的メタデータを提供することを望む傾向があるためです。
静的メタデータと動的メタデータの区別を要求することは、メタデータが指定されていない場合の曖昧さを排除するのにも役立ちます。メタデータが動的である可能性がある場合、メタデータが意図的に欠落しているのか、後で提供される予定なのかを知ることはできません。動的メタデータを指定することを要求することで、メタデータが指定されていない場合の意図が明確になります。
この PEP は、ビルドバックエンドによって必要とされるすべてのメタデータを標準化しようとするものではありません。コアメタデータ 仕様でカバーされているメタデータのみを対象とし、これらはプロジェクト間で非常に一般的であり、静的で一貫して指定されることから利益を得ることができます。これにより、ビルドバックエンドはホイールに含めるファイルの指定方法などのパターンについて引き続き革新することができます。また、ユーザーとビルドバックエンドがこの PEP の一部を選択的にオプトアウトするためのエスケープハッチも含まれています(完全にオプトアウトすることも可能です)。
この PEP は、コアメタデータ を変更しようとするものではありません。そのような考慮は別の PEP で行われるべきであり、この PEP で指定された内容に変更や追加が行われる可能性があります。
根拠
この PEP の著者が従った設計ガイドラインは次のとおりです:
- コアメタデータ のできるだけ多くを
pyproject.tomlに表現する - メタデータを静的に定義し、後でビルドバックエンドを介して動的に定義するためのエスケープハッチを提供する
- 適切な場合には馴染みのある名前を使用するが、より現代的な用語を使用することもいとわない
- ビルドバックエンドが低レベルでメタデータを指定する方法を反映するのではなく、TOML ファイル内で使いやすくする
- TOML をメタデータに使用している他のビルドバックエンドから学ぶ
- 低レベルで既存の標準がないものを標準化しようとしない
- この PEP を使用してメタデータが指定される場合、それは正規のものと見なされる
仕様
プロジェクトメタデータを指定する場合、ツールはこの PEP で指定されたメタデータに従い、尊重しなければなりません。メタデータが正しく指定されていない場合、ツールはエラーを発生させてユーザーにその間違いを通知しなければなりません。
この PEP を使用して指定されたデータは正規のものと見なされます。ツールは静的に指定されたデータを削除、追加、変更することはできません。フィールドが dynamic としてマークされている場合にのみ、ツールは「新しい」値を提供することができます。
詳細
テーブル名
ツールは、この PEP で定義されたフィールドを [project] という名前のテーブルに指定しなければなりません。このテーブルにこの PEP または後続の PEP で定義されていないフィールドを追加することはできません。ツールが pyproject.toml に独自の設定を保存したい場合、PEP 518 で定義されているように [tool] テーブルを使用することができます。[project] テーブルが存在しない場合、ビルドバックエンドはすべてのフィールドを動的に提供することを暗黙的に意味します。
name
プロジェクトの名前。
ツールはユーザーにこのフィールドを静的に定義することを要求しなければなりません。
ツールは、内部の一貫性のために、この名前を読み取った時点で PEP 503 で指定されたように正規化するべきです。
version
PEP 440 でサポートされているプロジェクトのバージョン。
ユーザーはすでに正規化されたバージョンを指定することを推奨します。
description
- フォーマット: 文字列
- コアメタデータ:
Summary(リンク) - 同義語
- Flit: N/A
- Poetry:
description(リンク) - Setuptools:
description(リンク)
プロジェクトの概要説明。
readme
プロジェクトの完全な説明(つまり README)。
このフィールドは文字列またはテーブルを受け入れます。文字列の場合、それは完全な説明を含むテキストファイルへの相対パスです。ツールはファイルのエンコーディングが UTF-8 であると仮定しなければなりません。ファイルパスが大文字小文字を区別しない .md サフィックスで終わる場合、ツールはコンテンツタイプが text/markdown であると仮定しなければなりません。ファイルパスが大文字小文字を区別しない .rst で終わる場合、ツールはコンテンツタイプが text/x-rst であると仮定しなければなりません。ツールがこの PEP で認識されていない拡張子を認識する場合、ユーザーのためにコンテンツタイプを推測することができますが、このフィールドを dynamic として指定する必要はありません。コンテンツタイプが提供されていない場合、ツールはエラーを発生させなければなりません。
readme フィールドはテーブルも受け入れます。file キーは完全な説明を含むファイルへの相対パスを表す文字列値を持ちます。text キーは完全な説明である文字列値を持ちます。これらのキーは相互排他的であるため、メタデータが両方のキーを指定している場合、ツールはエラーを発生させなければなりません。
readme フィールドに指定されたテーブルには、完全な説明のコンテンツタイプを指定する文字列値を持つ content-type フィールドもあります。メタデータがテーブル内でこのフィールドを指定していない場合、ツールはエラーを発生させなければなりません。メタデータが charset パラメータを指定していない場合、それは UTF-8 と見なされます。ツールは他のエンコーディングをサポートすることができます。ツールは、コアメタデータ でサポートされているコンテンツタイプに変換できる他のコンテンツタイプをサポートすることができます。それ以外の場合、ツールはサポートされていないコンテンツタイプに対してエラーを発生させなければなりません。
requires-python
プロジェクトの Python バージョン要件。
license
このテーブルには2つのキーのいずれかが含まれます。file キーはプロジェクトのライセンスを含むファイルへの相対パスを持つ文字列値です。ツールはファイルのエンコーディングが UTF-8 であると仮定しなければなりません。text キーはプロジェクトのライセンスである文字列値を持ち、その意味は コアメタデータ の License フィールドと同じです。これらのキーは相互排他的であるため、メタデータが両方のキーを指定している場合、ツールはエラーを発生させなければなりません。
license キーの実用的な文字列値は、将来の PEP が SPDX 式のサポートを指定するために意図的に省略されています(同じ論理が file または text が表すライセンスを指定するための「type」フィールドにも適用されます)。
keywords
プロジェクトのキーワード。
classifiers
プロジェクトに適用される Trove classifiers 。
urls
キーが URL ラベルで、値が URL 自体であるテーブル。
エントリポイント
- フォーマット: テーブル(
[project.scripts]、[project.gui-scripts]、および[project.entry-points]) - コアメタデータ: N/A; エントリポイント仕様
- 同義語
エントリポイントに関連する3つのテーブルがあります。[project.scripts] テーブルは、エントリポイント仕様 の console_scripts グループに対応します。テーブルのキーはエントリポイントの名前で、値はオブジェクト参照です。
[project.gui-scripts] テーブルは、エントリポイント仕様 の gui_scripts グループに対応します。その形式は [project.scripts] と同じです。
[project.entry-points] テーブルはテーブルのコレクションです。各サブテーブルの名前はエントリポイントグループです。キーと値のセマンティクスは [project.scripts] と同じです。ユーザーはネストされたサブテーブルを作成してはならず、エントリポイントグループを1レベルのみに保つ必要があります。
ビルドバックエンドは、メタデータが [project.entry-points.console_scripts] または [project.entry-points.gui_scripts] テーブルを定義している場合、エラーを発生させなければなりません。これは、[project.scripts] および [project.gui-scripts] と矛盾するためです。
dependencies/optional-dependencies
- フォーマット: PEP 508 文字列の配列(
dependencies)および PEP 508 文字列の配列を値とするテーブル(optional-dependencies) - コアメタデータ:
Requires-DistおよびProvides-Extra(リンク, リンク) - 同義語
プロジェクトの(オプションの)依存関係。
dependencies の場合、それは文字列の配列を値とするキーです。各文字列はプロジェクトの依存関係を表し、有効な PEP 508 文字列としてフォーマットされていなければなりません。各文字列は コアメタデータ の Requires-Dist エントリに直接マッピングされます。
optional-dependencies の場合、それは各キーがエクストラを指定し、値が文字列の配列であるテーブルです。配列の文字列は有効な PEP 508 文字列でなければなりません。キーは Provides-Extra コアメタデータ の有効な値でなければなりません。したがって、配列内の各値は、対応する Provides-Extra メタデータの対応する Requires-Dist エントリになります。
dynamic
- フォーマット: 文字列の配列
- コアメタデータ: N/A
- 同義語なし
この PEP でリストされているフィールドのうち、他のツールが動的にそのメタデータを提供するために意図的に指定されていないフィールドを指定します。これにより、メタデータが意図的に指定されていないことと、後でツールを介して提供される予定であることが明確に区別されます。
- ビルドバックエンドは静的に指定されたメタデータを尊重しなければなりません(つまり、メタデータが
dynamicにリストされていないことを意味します)。 - ビルドバックエンドは、メタデータが
dynamicにnameを指定している場合、エラーを発生させなければなりません。 - コアメタデータ 仕様がフィールドを「必須」としてリストしている場合、メタデータはフィールドを静的に指定するか、
dynamicにリストしなければなりません(ビルドバックエンドはそれ以外の場合にエラーを発生させなければなりません。つまり、必須フィールドが[project]テーブルに何らかの形でリストされていないことはできません)。 - コアメタデータ 仕様がフィールドを「オプション」としてリストしている場合、ビルドバックエンドが後でフィールドのデータを提供することを期待している場合、メタデータはそれを
dynamicにリストすることができます。 - メタデータがフィールドを静的に指定し、かつ
dynamicにリストしている場合、ビルドバックエンドはエラーを発生させなければなりません。 - メタデータがフィールドを
dynamicにリストしていない場合、ビルドバックエンドはユーザーに代わって必要なメタデータを埋めることはできません(つまり、dynamicはツールがメタデータを埋めることを許可する唯一の方法であり、ユーザーは埋めることにオプトインする必要があります)。 - メタデータがフィールドを動的に指定しているが、ビルドバックエンドがそのデータを提供できなかった場合、ビルドバックエンドはエラーを発生させなければなりません。
例
[project]
name = "spam"
version = "2020.0.0"
description = "Lovely Spam! Wonderful Spam!"
readme = "README.rst"
requires-python = ">=3.8"
license = {file = "LICENSE.txt"}
keywords = ["egg", "bacon", "sausage", "tomatoes", "Lobster Thermidor"]
authors = [
{email = "hi@pradyunsg.me"},
{name = "Tzu-ping Chung"}
]
maintainers = [
{name = "Brett Cannon", email = "brett@python.org"}
]
classifiers = [
"Development Status :: 4 - Beta",
"Programming Language :: Python"
]
dependencies = [
"httpx",
"gidgethub[httpx]>4.0.0",
"django>2.1; os_name != 'nt'",
"django>2.0; os_name == 'nt'"
]
[project.optional-dependencies]
test = [
"pytest < 5.0.0",
"pytest-cov[all]"
]
[project.urls]
homepage = "https://example.com"
documentation = "https://readthedocs.org"
repository = "https://github.com"
changelog = "https://github.com/me/spam/blob/master/CHANGELOG.md"
[project.scripts]
spam-cli = "spam:main_cli"
[project.gui-scripts]
spam-gui = "spam:main_gui"
[project.entry-points."spam.magical"]
tomatoes = "spam:main_tomatoes"
後方互換性
これはプロジェクトの コアメタデータ を指定する新しい方法を提供し、PEP 518 で概説されている予約された名前空間の新しいテーブル名を使用しているため、後方互換性の懸念はありません。
セキュリティの影響
この PEP はプロジェクトメタデータを静的に定義する方法をカバーしているため、直接的なセキュリティの懸念はありません。セキュリティの問題は、ツールがメタデータを消費し、それに基づいて行動する方法に起因する可能性があります。
参考実装
この PEP を実装しているビルドバックエンドの概念実証は現在ありません。
却下されたアイデア
他のテーブル名
[build-system] の下にあるもの
このテーブル名を使用すると、ビルドメタデータとプロジェクトメタデータの混乱が悪化する可能性があるという懸念がありました。たとえば、[build-system.metadata] というテーブルを使用する場合です。
[package]
強い支持は得られませんでした。
[metadata]
[project] の次に強い候補でしたが、最終的には [project] が一部のサブテーブルに対してより読みやすいと合意されました。たとえば、[project.urls] です。
メタデータプロバイダーのサポート
最初は、この PEP で指定された静的メタデータと PEP 517 で指定された prepare_metadata_for_build_wheel() の間に中間層を追加する提案がありました。アイデアは、プロジェクトがビルドバックエンドとメタデータの間に挿入したい場合、そのためのフックを提供することでした。
最終的に、著者はこのアイデアが不必要に複雑であり、コアメタデータをできるだけ静的に定義するように人々を促すという設計目標から逸脱することを考慮しました。
正規化されたプロジェクト名を要求する
ツールが PEP 503 で指定された正規化された名前のみを使用する方が簡単であると考えられましたが、このアイデアは最終的にこの PEP を使用するプロジェクトの移行を妨げるため却下されました。
ビルド時に含めるファイルを指定する
著者は設計ディスカッションの中で、この PEP はプロジェクトメタデータに専念し、ビルドメタデータには専念しないことを早期に決定しました。そのため、ソースディストリビューションやホイールファイルに含めるファイルを指定することは、この PEP の範囲外です。
[project.urls] テーブルを [project.project-urls] と命名する
この提案は、対応する コアメタデータ が Project-Url であることに基づいています。しかし、[project] の全体的なテーブル名が選ばれた後、「プロジェクト」という単語の冗長な使用が現在の短い名前の方が適していることを示唆しました。
別の url/home-page フィールドを持つ
コアメタデータ がサポートしている一方で、プロジェクトの URL のための単一のフィールドを持ちながら、完全なテーブルをサポートすることは冗長であり、混乱を招くと考えられました。
ツールが開発関連の依存関係を「dev」エクストラに配置することを推奨する
さまざまなツールが必須依存関係と開発依存関係の概念を成長させる中で、ツールがそのような開発ツールを「dev」グループに配置することを提案するアイデアが浮上しました。しかし、最終的には、著者はこの仕様がそのようなワークフローを提案することは範囲外であると判断しました。
dynamic フィールドが欠落している必須フィールドのみを指定することを要求する
著者は、dynamic フィールドが欠落している必須フィールドのみをリストし、オプションフィールドのリストをオプションにするアイデアを検討しました。しかし、最終的には、できるだけ多くの情報を静的に指定することを促進するという設計目標に反するため、このアイデアは却下されました。
readme フィールドの異なる構造
readme フィールドには readme_content_type フィールドが提案されましたが、著者は文字列/テーブルのハイブリッド形式が一般的なケースに対してより実用的であり、より複雑なケースにも対応できると考えました。同様に、long_description と対応する long_description_content_type フィールドを使用することも提案されました。
テーブル形式の file キーは最初 path として提案されましたが、file は setuptools の file キーに対応しており、他に強い理由がない限り、どちらを選ぶかは重要ではありません。
readme フィールドが text/plain を暗示することを許可する
著者は、指定されていないコンテンツタイプを許可し、それを text/plain と見なすことを検討しましたが、PyPI での誤ったレンダリングを防ぐために、この場合は明示的にすることが最善であると判断しました。
dependencies/optional-dependencies の他の名前
著者は最初に requires/extra-requires という名前を提案しましたが、他のパッケージングエコシステムの調査の結果、Python が例外であることが示されたため、現在の名前を選択しました:
現在の名前に正規化することで、他のエコシステムから来る人々の混乱を最小限に抑え、新しいプログラマーにとっても馴染みのない用語を使用することを避けることができます。また、PEP 518 で指定された [build-system] テーブルの requires と混同する可能性も防ぎます。
project.entry-points のテーブルの任意の深さをサポートする
サブテーブルの深さを1に制限することが、ユーザーがドット付きの名前を使用し、テーブル名に引用符を使用することに慣れていない場合に混乱を引き起こす可能性があるという懸念がありました(例:project.entry-points."spam.magical")。しかし、任意の深さをサポートすること(例:project.entry-points.spam.magical)は、将来の展開されたテーブル形式のいかなる形態も排除します。また、ビルドバックエンドにとって、単一レベルではなく完全なテーブル構造をトラバースし、値の型に応じて適切にエラーを発生させる必要があるため、複雑化します。
依存関係を指定するために構造化された TOML 辞書を使用する
プロジェクトの依存関係を指定する形式は、データ形式に関して最も議論されたトピックでした。これにより、この PEP と TOML 辞書をより広範に使用する PEP 631 および PEP 633 が作成されました。これらの PEP に関する決定は、https://discuss.python.org/t/how-to-specify-dependencies-pep-508-strings-or-a-table-in-toml/5243/38 で見つけることができます。
著者は一時的に両方の形式をサポートすることを検討しましたが、2つの形式に精通する必要があるため、混乱を招くと判断しました。
ビルドバックエンドが sdist を生成する際に pyproject.toml を更新することを要求する
この PEP が書かれた時点では、sdist にはこの PEP のような静的で正規のメタデータが必要ありませんでした。そのため、この PEP を使用して sdist にそのようなメタデータを取得することが検討されました。しかし、最終的には、pyproject.toml を更新するというアイデアは一般的に好まれず、sdist のメタデータを標準化することを別途追求するために却下されました。
ツールがデータを追加/拡張することを許可する
この PEP の初期バージョンでは、ツールがフィールドのデータを拡張することが許可されていました。たとえば、ビルドバックエンドはバージョン番号を取得し、ホイールをビルドする際にローカルバージョンを追加することができました。ツールは、ライセンスやサポートされている Python バージョンなどのために、より多くのトローブ分類子を追加することもできました。
しかし、最終的には、データの静的性を緩和する方法を現実の使用に基づいて検討する前に、より厳格に開始する方が良いと考えられました。
未解決の問題
現在のところありません。
著作権
このドキュメントはパブリックドメインに置かれているか、CC0-1.0-Universal ライセンスの下に置かれています。どちらがより寛容かによります。
Source: https://github.com/python/peps/blob/main/peps/pep-0621.rst
Last modified: 2024-10-22 05:20:14 GMT