Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#2044 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussions-To: https://discuss.python.org/t/pep-621-round-3/5472
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: https://discuss.python.org/t/pep-621-round-3/5472/109
.. canonical-pypa-spec:: :ref:
packaging:pyproject-toml-specAbstract
This PEP specifies how to write a project's
core metadata_ in apyproject.tomlfile for packaging-related tools to consume.Motivation
The key motivators of this PEP are:
ease of specification, unambiguity, and deterministic consumption by
build back-ends
learning and transitioning between build back-ends
"boring parts" of a project's metadata
To speak specifically to the motivation for static metadata, that has
been an overall goal of the packaging ecosystem for some time. As
such, making it easy to specify metadata statically is important. This
also means that raising the cost of specifying data as dynamic is
acceptable as users should skew towards wanting to provide static
metadata.
Requiring the distinction between static and dynamic metadata also
helps with disambiguation for when metadata isn't specified. When any
metadata may be dynamic, it means you never know if the absence of
metadata is on purpose or because it is to be provided later. By
requiring that dynamic metadata be specified, it disambiguates the
intent when metadata goes unspecified.
This PEP does not attempt to standardize all possible metadata
required by a build back-end, only the metadata covered by the
core metadata_ specification which are very common across projectsand would stand to benefit from being static and consistently
specified. This means build back-ends are still free and able to
innovate around patterns like how to specify the files to include in a
wheel. There is also an included escape hatch for users and build
back-ends to use when they choose to partially opt-out of this PEP
(compared to opting-out of this PEP entirely, which is also possible).
This PEP is also not trying to change the underlying
core metadata_in any way. Such considerations should be done in a separate PEP which
may lead to changes or additions to what this PEP specifies.
Rationale
The design guidelines the authors of this PEP followed were:
core metadata_ inpyproject.tomlas is reasonablewant to define it dynamically later via a build back-end
modern terminology
build back-ends specify metadata at a low-level when it makes sense
have used TOML for their metadata
at a lower-level
canonical
Specification
When specifying project metadata, tools MUST adhere and honour the
metadata as specified in this PEP. If metadata is improperly specified
then tools MUST raise an error to notify the user about their mistake.
Data specified using this PEP is considered canonical. Tools CANNOT
remove, add or change data that has been statically specified. Only
when a field is marked as
dynamicmay a tool provide a "new" value.Details
Table name
''''''''''
Tools MUST specify fields defined by this PEP in a table named
[project]. No tools may add fields to this table which are notdefined by this PEP or subsequent PEPs. For tools wishing to store
their own settings in
pyproject.toml, they may use the[tool]table as defined in :pep:
518. The lack of a[project]tableimplicitly means the build back-end will dynamically provide all
fields.
name''''''''
Format: string
Core metadata_:Name(
link <https://packaging.python.org/specifications/core-metadata/#name>__)Synonyms
module/dist-name(
link <https://flit.readthedocs.io/en/latest/pyproject_toml.html#metadata-section>__)name(
link <https://python-poetry.org/docs/pyproject/#name>__)name(
link <https://setuptools.readthedocs.io/en/latest/setuptools.html#metadata>__)The name of the project.
Tools MUST require users to statically define this field.
Tools SHOULD normalize this name, as specified by :pep:
503, as soonas it is read for internal consistency.
version'''''''''''
Format: string
Core metadata_:Version(
link <https://packaging.python.org/specifications/core-metadata/#version>__)Synonyms
__version__attribute)(
link <https://flit.readthedocs.io/en/latest/index.html#usage>__)version(
link <https://python-poetry.org/docs/pyproject/#version>__)version(
link <https://setuptools.readthedocs.io/en/latest/setuptools.html#metadata>__)The version of the project as supported by :pep:
440.Users SHOULD prefer to specify already-normalized versions.
description'''''''''''''''
Format: string
Core metadata_:Summary(
link <https://packaging.python.org/specifications/core-metadata/#summary>__)Synonyms
description(
link <https://python-poetry.org/docs/pyproject/#description>__)description(
link <https://setuptools.readthedocs.io/en/latest/setuptools.html#metadata>__)The summary description of the project.
readme''''''''''
Format: String or table
Core metadata_:Description(
link <https://packaging.python.org/specifications/core-metadata/#description>__)Synonyms
description-file(
link <https://flit.readthedocs.io/en/latest/pyproject_toml.html#metadata-section>__)readme(
link <https://python-poetry.org/docs/pyproject/#readme>__)long_description(
link <https://setuptools.readthedocs.io/en/latest/setuptools.html#metadata>__)The full description of the project (i.e. the README).
The field accepts either a string or a table. If it is a string then
it is the relative path to a text file containing the full
description. Tools MUST assume the file's encoding is UTF-8. If the
file path ends in a case-insensitive
.mdsuffix, then tools MUSTassume the content-type is
text/markdown. If the file path ends ina case-insensitive
.rst, then tools MUST assume the content-typeis
text/x-rst. If a tool recognizes more extensions than this PEP,they MAY infer the content-type for the user without specifying this
field as
dynamic. For all unrecognized suffixes when acontent-type is not provided, tools MUST raise an error.
The
readmefield may also take a table. Thefilekey has astring value representing a relative path to a file containing the
full description. The
textkey has a string value which is thefull description. These keys are mutually-exclusive, thus tools MUST
raise an error if the metadata specifies both keys.
A table specified in the
readmefield also has acontent-typefield which takes a string specifying the content-type of the full
description. A tool MUST raise an error if the metadata does not
specify this field in the table. If the metadata does not specify the
charsetparameter, then it is assumed to be UTF-8. Tools MAYsupport other encodings if they choose to. Tools MAY support
alternative content-types which they can transform to a content-type
as supported by the
core metadata_. Otherwise tools MUST raise anerror for unsupported content-types.
requires-python'''''''''''''''''''
Format: string
Core metadata_:Requires-Python(
link <https://packaging.python.org/specifications/core-metadata/#summary>__)Synonyms
requires-python(
link <https://flit.readthedocs.io/en/latest/pyproject_toml.html#metadata-section>__)pythondependency in the[tool.poetry.dependencies]table(
link <https://python-poetry.org/docs/pyproject/#dependencies-and-dev-dependencies>__)python_requires(
link <https://setuptools.readthedocs.io/en/latest/setuptools.html#metadata>__)The Python version requirements of the project.
license'''''''''''
Format: Table
Core metadata_:License(
link <https://packaging.python.org/specifications/core-metadata/#license>__)Synonyms
license(
link <https://flit.readthedocs.io/en/latest/pyproject_toml.html#metadata-section>__)license(
link <https://python-poetry.org/docs/pyproject/#license>__)license,license_file,license_files(
link <https://setuptools.readthedocs.io/en/latest/setuptools.html#metadata>__)The table may have one of two keys. The
filekey has a stringvalue that is a relative file path to the file which contains the
license for the project. Tools MUST assume the file's encoding is
UTF-8. The
textkey has a string value which is the license of theproject whose meaning is that of the
Licensefield from thecore metadata_. These keys are mutually exclusive, so a tool MUSTraise an error if the metadata specifies both keys.
A practical string value for the
licensekey has been purposefullyleft out to allow for a future PEP to specify support for SPDX_
expressions (the same logic applies to any sort of "type" field
specifying what license the
fileortextrepresents).authors/maintainers'''''''''''''''''''''''''''
Format: Array of inline tables with string keys and values
Core metadata_:Author/Author-email/Maintainer/Maintainer-email(
link <https://packaging.python.org/specifications/core-metadata/#author>__)Synonyms
author/author-email/maintainer/maintainer-email(
link <https://flit.readthedocs.io/en/latest/pyproject_toml.html#metadata-section>__)authors/maintainers(
link <https://python-poetry.org/docs/pyproject/#authors>__)author/author_email/maintainer/maintainer_email(
link <https://setuptools.readthedocs.io/en/latest/setuptools.html#metadata>__)The people or organizations considered to be the "authors" of the
project. The exact meaning is open to interpretation — it may list the
original or primary authors, current maintainers, or owners of the
package.
The "maintainers" field is similar to "authors" in that its exact
meaning is open to interpretation.
These fields accept an array of tables with 2 keys:
nameandemail. Both values must be strings. Thenamevalue MUST be avalid email name (i.e. whatever can be put as a name, before an email,
in :rfc:
822) and not contain commas. Theemailvalue MUST be avalid email address. Both keys are optional.
Using the data to fill in
core metadata_ is as follows:nameis provided, the value goes inAuthor/Maintaineras appropriate.emailis provided, the value goes inAuthor-email/Maintainer-emailas appropriate.emailandnameare provided, the value goes inAuthor-email/Maintainer-emailas appropriate, with theformat
{name} <{email}>(with appropriate quoting, e.g. usingemail.headerregistry.Address).keywords''''''''''''
Format: array of strings
Core metadata_:Keywords(
link <https://packaging.python.org/specifications/core-metadata/#keywords>__)Synonyms
keywords(
link <https://flit.readthedocs.io/en/latest/pyproject_toml.html#metadata-section>__)keywords(
link <https://python-poetry.org/docs/pyproject/#keywords>_)keywords(
link <https://setuptools.readthedocs.io/en/latest/setuptools.html#metadata>__)The keywords for the project.
classifiers'''''''''''''''
Format: array of strings
Core metadata_:Classifier(
link <https://packaging.python.org/specifications/core-metadata/#classifier-multiple-use>__)Synonyms
classifiers(
link <https://flit.readthedocs.io/en/latest/pyproject_toml.html#metadata-section>__)classifiers(
link <https://python-poetry.org/docs/pyproject/#classifiers>__)classifiers(
link <https://setuptools.readthedocs.io/en/latest/setuptools.html#metadata>__)Trove classifiers_ which apply to the project.urls''''''''
Format: Table, with keys and values of strings
Core metadata_:Project-URL(
link <https://packaging.python.org/specifications/core-metadata/#project-url-multiple-use>__)Synonyms
[tool.flit.metadata.urls]table(
link <https://flit.readthedocs.io/en/latest/pyproject_toml.html#metadata-section>__)[tool.poetry.urls]table(
link <https://python-poetry.org/docs/pyproject/#urls>__)project_urls(
link <https://setuptools.readthedocs.io/en/latest/setuptools.html#metadata>__)A table of URLs where the key is the URL label and the value is the
URL itself.
Entry points
''''''''''''
Format: Table (
[project.scripts],[project.gui-scripts], and[project.entry-points])Core metadata: N/A;Entry points specificationSynonyms
[tool.flit.scripts]table for console scripts,[tool.flit.entrypoints]for the rest(
link <https://flit.readthedocs.io/en/latest/pyproject_toml.html#scripts-section>__)[tool.poetry.scripts]table for console scripts(
link <https://python-poetry.org/docs/pyproject/#scripts>__)entry_points(
link <https://setuptools.readthedocs.io/en/latest/setuptools.html#metadata>__)There are three tables related to entry points. The
[project.scripts]table corresponds to theconsole_scriptsgroup in the
entry points specification_. The key of the table is the name of theentry point and the value is the object reference.
The
[project.gui-scripts]table corresponds to thegui_scriptsgroup in the
entry points specification_. Its format is the same as[project.scripts].The
[project.entry-points]table is a collection of tables. Eachsub-table's name is an entry point group. The key and value semantics
are the same as
[project.scripts]. Users MUST NOT createnested sub-tables but instead keep the entry point groups to only one
level deep.
Build back-ends MUST raise an error if the metadata defines a
[project.entry-points.console_scripts]or[project.entry-points.gui_scripts]table, as they wouldbe ambiguous in the face of
[project.scripts]and[project.gui-scripts], respectively.dependencies/optional-dependencies''''''''''''''''''''''''''''''''''''''''''
Format: Array of :pep:
508strings (dependencies) and a tablewith values of arrays of :pep:
508strings(
optional-dependencies)Core metadata_:Requires-DistandProvides-Extra(
link <https://packaging.python.org/specifications/core-metadata/#requires-dist-multiple-use>,link <https://packaging.python.org/specifications/core-metadata/#provides-extra-multiple-use>)Synonyms
requiresfor required dependencies,requires-extrafor optional dependencies
(
link <https://flit.readthedocs.io/en/latest/pyproject_toml.html#metadata-section>__)[tool.poetry.dependencies]for dependencies (bothrequired and for development),
[tool.poetry.extras]for optional dependencies(
link <https://python-poetry.org/docs/pyproject/#dependencies-and-dev-dependencies>__)install_requiresfor required dependencies,extras_requirefor optional dependencies(
link <https://setuptools.readthedocs.io/en/latest/setuptools.html#metadata>__)The (optional) dependencies of the project.
For
dependencies, it is a key whose value is an array of strings.Each string represents a dependency of the project and MUST be
formatted as a valid :pep:
508string. Each string maps directly toa
Requires-Distentry in thecore metadata_.For
optional-dependencies, it is a table where each key specifiesan extra and whose value is an array of strings. The strings of the
arrays must be valid :pep:
508strings. The keys MUST be valid valuesfor the
Provides-Extracore metadata_. Each value in the arraythus becomes a corresponding
Requires-Distentry for the matchingProvides-Extrametadata.dynamic'''''''''''
Core metadata_: N/ASpecifies which fields listed by this PEP were intentionally
unspecified so another tool can/will provide such metadata
dynamically. This clearly delineates which metadata is purposefully
unspecified and expected to stay unspecified compared to being
provided via tooling later on.
means the metadata did not list the field in
dynamic).nameindynamic.core metadata_ specification lists a field as "Required",then the metadata MUST specify the field statically or list it in
dynamic(build back-ends MUST raise an error otherwise, i.e. itshould not be possible for a required field to not be listed somehow
in the
[project]table).core metadata_ specification lists a field as "Optional",the metadata MAY list it in
dynamicif the expectation is abuild back-end will provide the data for the field later.
field statically as well as being listed in
dynamic.dynamic, then a buildback-end CANNOT fill in the requisite metadata on behalf of the user
(i.e.
dynamicis the only way to allow a tool to fill inmetadata and the user must opt into the filling in).
field in dynamic but the build back-end was unable to provide the
data for it.
Example
::
[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"
Backwards Compatibility
As this prov