Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an example and list of keys to the project metadata spec #1168

Merged
merged 6 commits into from
Dec 4, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions source/specifications/core-metadata.rst
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ a single ``-`` character. This can be done using the following snippet of code

re.sub(r"[-_.]+", "-", name).lower()


.. _core-metadata-version:

Version
Expand All @@ -106,6 +107,8 @@ Example::
Version: 1.0a2


.. _core-metadata-dynamic:

Dynamic (multiple use)
======================

Expand Down
160 changes: 122 additions & 38 deletions source/specifications/declaring-project-metadata.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,60 @@ Declaring project metadata
packaging-related tools to consume. It defines the following
specification as the canonical source for the format used.


Specification
=============

There are two kinds of metadata: *static* and *dynamic*. Static
metadata is specified in the ``pyproject.toml`` file directly and
cannot be specified or changed by a tool. Dynamic metadata is listed
via the ``dynamic`` field (defined later in this specification) and
via the ``dynamic`` key (defined later in this specification) and
represents metadata that a tool will later provide.

The fields defined in this specification MUST be in a table named
``[project]`` in ``pyproject.toml``. No tools may add fields to this
The keys defined in this specification MUST be in a table named
``[project]`` in ``pyproject.toml``. No tools may add keys to this
table which are not defined by this specification. For tools wishing
to store their own settings in ``pyproject.toml``, they may use the
``[tool]`` table as defined in the
:ref:`build dependency declaration specification <declaring-build-dependencies>`.
The lack of a ``[project]`` table implicitly means the build back-end
will dynamically provide all fields.
will dynamically provide all keys.

The only fields required to be statically defined are:
The only keys required to be statically defined are:

- ``name``

The fields which are required but may be specified *either* statically
The keys which are required but may be specified *either* statically
or listed as dynamic are:

- ``version``

All other fields are considered optional and may be specified
All other keys are considered optional and may be specified
statically, listed as dynamic, or left unspecified.

The complete list of keys allowed in the ``[project]`` table are:

- ``authors``
- ``classifiers``
- ``dependencies``
- ``description``
- ``dynamic``
- ``entry-points``
- ``gui-scripts``
- ``keywords``
- ``license``
- ``maintainers``
- ``name``
- ``optional-dependencies``
- ``readme``
- ``requires-python``
- ``scripts``
- ``urls``
- ``version``


``name``
========
--------

- TOML_ type: string
- Corresponding :ref:`core metadata <core-metadata>` field:
Expand All @@ -51,7 +75,7 @@ as it is read for internal consistency.


``version``
===========
-----------

- TOML_ type: string
- Corresponding :ref:`core metadata <core-metadata>` field:
Expand All @@ -63,7 +87,7 @@ Users SHOULD prefer to specify already-normalized versions.


``description``
===============
---------------

- TOML_ type: string
- Corresponding :ref:`core metadata <core-metadata>` field:
Expand All @@ -73,7 +97,7 @@ The summary description of the project.


``readme``
==========
----------

- TOML_ type: string or table
- Corresponding :ref:`core metadata <core-metadata>` field:
Expand All @@ -82,28 +106,28 @@ The summary description of the project.

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
The key accepts either a string or a table. If it is a string then
it is a path relative to ``pyproject.toml`` 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 ``.md`` suffix, then tools
MUST assume the content-type is ``text/markdown``. If the file path
ends in a case-insensitive ``.rst``, then tools MUST assume the
content-type is ``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
specifying this key as ``dynamic``. For all unrecognized suffixes
when a content-type is not provided, tools MUST raise an error.

The ``readme`` field may also take a table. The ``file`` key has a
The ``readme`` key may also take a table. The ``file`` key has a
string value representing a path relative to ``pyproject.toml`` to a
file containing the full description. The ``text`` key has a string
value which is the full description. These keys are
mutually-exclusive, thus tools MUST raise an error if the metadata
specifies both keys.

A table specified in the ``readme`` field also has a ``content-type``
field which takes a string specifying the content-type of the full
A table specified in the ``readme`` key also has a ``content-type``
key 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
specify this key in the table. If the metadata does not specify the
``charset`` parameter, then it is assumed to be UTF-8. Tools MAY
support other encodings if they choose to. Tools MAY support
alternative content-types which they can transform to a content-type
Expand All @@ -112,7 +136,7 @@ tools MUST raise an error for unsupported content-types.


``requires-python``
===================
-------------------

- TOML_ type: string
- Corresponding :ref:`core metadata <core-metadata>` field:
Expand All @@ -122,7 +146,7 @@ The Python version requirements of the project.


``license``
===========
-----------

- TOML_ type: table
- Corresponding :ref:`core metadata <core-metadata>` field:
Expand All @@ -137,7 +161,7 @@ tool MUST raise an error if the metadata specifies both keys.


``authors``/``maintainers``
===========================
---------------------------

- TOML_ type: Array of inline tables with string keys and values
- Corresponding :ref:`core metadata <core-metadata>` field:
Expand All @@ -151,10 +175,10 @@ 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
The "maintainers" key is similar to "authors" in that its exact
meaning is open to interpretation.

These fields accept an array of tables with 2 keys: ``name`` and
These keys accept an array of tables with 2 keys: ``name`` and
``email``. Both values must be strings. The ``name`` value MUST be a
valid email name (i.e. whatever can be put as a name, before an email,
in :rfc:`822`) and not contain commas. The ``email`` value MUST be a
Expand All @@ -179,7 +203,7 @@ follows:


``keywords``
============
------------

- TOML_ type: array of strings
- Corresponding :ref:`core metadata <core-metadata>` field:
Expand All @@ -189,7 +213,7 @@ The keywords for the project.


``classifiers``
===============
---------------

- TOML_ type: array of strings
- Corresponding :ref:`core metadata <core-metadata>` field:
Expand All @@ -199,7 +223,7 @@ Trove classifiers which apply to the project.


``urls``
========
--------

- TOML_ type: table with keys and values of strings
- Corresponding :ref:`core metadata <core-metadata>` field:
Expand All @@ -210,7 +234,7 @@ URL itself.


Entry points
============
------------

- TOML_ type: table (``[project.scripts]``, ``[project.gui-scripts]``,
and ``[project.entry-points]``)
Expand Down Expand Up @@ -240,7 +264,7 @@ be ambiguous in the face of ``[project.scripts]`` and


``dependencies``/``optional-dependencies``
==========================================
------------------------------------------

- TOML_ type: Array of :pep:`508` strings (``dependencies``), and a
table with values of arrays of :pep:`508` strings
Expand All @@ -267,41 +291,101 @@ metadata.


``dynamic``
===========
-----------

- TOML_ type: array of string
- A corresponding :ref:`core metadata <core-metadata>` field does not
exist
- Corresponding :ref:`core metadata <core-metadata>` field:
:ref:`Dynamic <core-metadata-dynamic>`

Specifies which fields listed by this PEP were intentionally
Specifies which keys 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.

- A build back-end MUST honour statically-specified metadata (which
means the metadata did not list the field in ``dynamic``).
means the metadata did not list the key in ``dynamic``).
- A build back-end MUST raise an error if the metadata specifies
``name`` in ``dynamic``.
- If the :ref:`core metadata <core-metadata>` specification lists a
field as "Required", then the metadata MUST specify the field
field as "Required", then the metadata MUST specify the key
statically or list it in ``dynamic`` (build back-ends MUST raise an
error otherwise, i.e. it should not be possible for a required field
error otherwise, i.e. it should not be possible for a required key
to not be listed somehow in the ``[project]`` table).
- If the :ref:`core metadata <core-metadata>` specification lists a
field as "Optional", the metadata MAY list it in ``dynamic`` if the
expectation is a build back-end will provide the data for the field
expectation is a build back-end will provide the data for the key
later.
- Build back-ends MUST raise an error if the metadata specifies a
field statically as well as being listed in ``dynamic``.
- If the metadata does not list a field in ``dynamic``, then a build
key statically as well as being listed in ``dynamic``.
- If the metadata does not list a key in ``dynamic``, then a build
back-end CANNOT fill in the requisite metadata on behalf of the user
(i.e. ``dynamic`` is the only way to allow a tool to fill in
metadata and the user must opt into the filling in).
- Build back-ends MUST raise an error if the metadata specifies a
field in ``dynamic`` but the build back-end was unable to determine
key in ``dynamic`` but the build back-end was unable to determine
the data for it (omitting the data, if determined to be the accurate
value, is acceptable).


Example
=======

.. code-block:: toml

[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 = "[email protected]"},
{name = "Tzu-Ping Chung"}
]
maintainers = [
{name = "Brett Cannon", email = "[email protected]"}
]
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'"
]

# dynamic = ["version", "description"]

[project.optional-dependencies]
test = [
"pytest > 5.0.0",
"pytest-cov[all]"
]
doc = [
"sphinx",
"furo"
]

[project.urls]
homepage = "https://example.com"
documentation = "https://readthedocs.org"
repository = "https://github.com/me/spam.git"
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"


.. _TOML: https://toml.io