diff --git a/source/specifications/build-system-interface.rst b/source/specifications/build-system-interface.rst index 6b4b43133..781b8d797 100644 --- a/source/specifications/build-system-interface.rst +++ b/source/specifications/build-system-interface.rst @@ -24,83 +24,6 @@ combination of wheels and sdists. In a command like ``pip install lxml==2.4.0``, pip is acting as an integration frontend. -Source trees -============ - -There is an existing, legacy source tree format involving -``setup.py``. We don't try to specify it further; its de facto -specification is encoded in the source code and documentation of -``distutils``, ``setuptools``, ``pip``, and other tools. We'll refer -to it as the ``setup.py``\-style. - -Here we define a new style of source tree based around the -``pyproject.toml`` file defined in :pep:`518`, extending the -``[build-system]`` table in that file with one additional key, -``build-backend``. Here's an example of how it would look:: - - [build-system] - # Defined by PEP 518: - requires = ["flit"] - # Defined by this PEP: - build-backend = "flit.api:main" - -``build-backend`` is a string naming a Python object that will be -used to perform the build (see below for details). This is formatted -following the same ``module:object`` syntax as a ``setuptools`` entry -point. For instance, if the string is ``"flit.api:main"`` as in the -example above, this object would be looked up by executing the -equivalent of:: - - import flit.api - backend = flit.api.main - -It's also legal to leave out the ``:object`` part, e.g. :: - - build-backend = "flit.api" - -which acts like:: - - import flit.api - backend = flit.api - -Formally, the string should satisfy this grammar:: - - identifier = (letter | '_') (letter | '_' | digit)* - module_path = identifier ('.' identifier)* - object_path = identifier ('.' identifier)* - entry_point = module_path (':' object_path)? - -And we import ``module_path`` and then lookup -``module_path.object_path`` (or just ``module_path`` if -``object_path`` is missing). - -When importing the module path, we do *not* look in the directory containing the -source tree, unless that would be on ``sys.path`` anyway (e.g. because it is -specified in PYTHONPATH). Although Python automatically adds the working -directory to ``sys.path`` in some situations, code to resolve the backend should -not be affected by this. - -If the ``pyproject.toml`` file is absent, or the ``build-backend`` -key is missing, the source tree is not using this specification, and -tools should revert to the legacy behaviour of running ``setup.py`` (either -directly, or by implicitly invoking the ``setuptools.build_meta:__legacy__`` -backend). - -Where the ``build-backend`` key exists, this takes precedence and the source tree follows the format and -conventions of the specified backend (as such no ``setup.py`` is needed unless the backend requires it). -Projects may still wish to include a ``setup.py`` for compatibility with tools that do not use this spec. - -This PEP also defines a ``backend-path`` key for use in ``pyproject.toml``, see -the "In-Tree Build Backends" section below. This key would be used as follows:: - - [build-system] - # Defined by PEP 518: - requires = ["flit"] - # Defined by this PEP: - build-backend = "local_backend" - backend-path = ["backend"] - - Build requirements ================== @@ -451,6 +374,8 @@ package *authors*, while still allowing *end-users* to open up the hood and apply duct tape when necessary. +.. _in-tree-build-backends: + In-tree build backends ---------------------- diff --git a/source/specifications/pyproject-toml.rst b/source/specifications/pyproject-toml.rst index 21cd2340d..102e841af 100644 --- a/source/specifications/pyproject-toml.rst +++ b/source/specifications/pyproject-toml.rst @@ -13,7 +13,8 @@ The ``pyproject.toml`` file acts as a configuration file for packaging-related tools (as well as other tools). -.. note:: This specification was originally defined in :pep:`518` and :pep:`621`. +.. note:: This specification was originally defined in :pep:`518`, + :pep:`517` and :pep:`621`. The ``pyproject.toml`` file is written in `TOML `_. Three tables are currently specified, namely @@ -29,71 +30,100 @@ Declaring build system dependencies: the ``[build-system]`` table The ``[build-system]`` table declares any Python level dependencies that must be installed in order to run the project's build system -successfully. +successfully. The valid keys are ``requires``, ``build-backend`` and +``backend-path``. -.. TODO: merge with PEP 517 +Tools should not require the existence of the ``[build-system]`` table. +A ``pyproject.toml`` file may be used to store configuration details +other than build-related data and thus lack a ``[build-system]`` table +legitimately. +If the table is specified but is missing required fields then the tool +should consider it an error. + + +``requires`` +------------ + +The ``requires`` key must have a value of a list of strings representing +dependencies required to execute the build system [#requires-json-schema]_. +The strings in this list follow the :ref:`version specifier specification +`. -The ``[build-system]`` table is used to store build-related data. -Initially, only one key of the table is valid and is mandatory -for the table: ``requires``. This key must have a value of a list -of strings representing dependencies required to execute the -build system. The strings in this list follow the :ref:`version specifier -specification `. +This key is mandatory if the ``[build-system]`` table is present. If +the ``pyproject.toml`` file is missing, or exists but is lacking the +``[build-system]`` table, then ``requires`` defaults to ``["setuptools"]``. -An example ``[build-system]`` table for a project built with -``setuptools`` is: + + +``build-backend`` +----------------- + +The ``build-backend`` key is a string naming a Python object that will be +used to perform the build. This is formatted following the same +``module:object`` syntax as an :ref:`entry point `. +For instance, with the configuration .. code-block:: toml [build-system] - # Minimum requirements for the build system to execute. - requires = ["setuptools"] + requires = ["backend-name"] + build-backend = "backend_name.build_system:backend" -Build tools are expected to use the example configuration file above as -their default semantics when a ``pyproject.toml`` file is not present. +this object would be looked up by executing the equivalent of:: -Tools should not require the existence of the ``[build-system]`` table. -A ``pyproject.toml`` file may be used to store configuration details -other than build-related data and thus lack a ``[build-system]`` table -legitimately. If the file exists but is lacking the ``[build-system]`` -table then the default values as specified above should be used. -If the table is specified but is missing required fields then the tool -should consider it an error. + import backend_name.build + backend = backend_name.build_system.backend +It is also legal to leave out the ``:object`` part, e.g. -To provide a type-specific representation of the resulting data from -the TOML file for illustrative purposes only, the following -`JSON Schema `_ would match the data format: +.. code-block:: toml -.. code-block:: json + build-backend = "backend_name.build_system" - { - "$schema": "http://json-schema.org/schema#", +which acts like:: - "type": "object", - "additionalProperties": false, + import backend_name.build_system + backend = backend_name.build_system - "properties": { - "build-system": { - "type": "object", - "additionalProperties": false, +Formally, the string should satisfy this grammar: - "properties": { - "requires": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": ["requires"] - }, +.. code-block:: text + + identifier = (letter | '_') (letter | '_' | digit)* + module_path = identifier ('.' identifier)* + object_path = identifier ('.' identifier)* + entry_point = module_path (':' object_path)? + +The module specified by ``module_path`` is imported and the build +backend object is looked up using ``module_path.object_path`` (or +``module_path`` is directly used if ``object_path`` is missing). +See :ref:`build-system-interface` for how the build backend object +is used to perform the build. + +When importing the module path, we do *not* look in the directory +containing the source tree, unless that would be on ``sys.path`` anyway +(e.g. because it is specified in PYTHONPATH). Although Python +automatically adds the working directory to ``sys.path`` in some +situations, code to resolve the backend should not be affected by this. + +Unlike the ``requires`` key, the ``build-backend`` key is optional +[#build-backend-optional]_. If ``pyproject.toml`` is absent, or +the ``[build-system]`` table is missing, or it does not contain +the ``build-backend`` key, build frontends should revert to the legacy +behavior of running ``setup.py`` (either directly, or implicitly by +invoking the ``setuptools.build_meta:__legacy__`` backend). + + +``backend-path`` +---------------- + +This key is for use by projects wishing to include their build backend +directly in their source tree, such as build backends themselves. If +provided, it must be a list of directories, which are prepended to +``sys.path`` during the build. For details, see +:ref:`in-tree-build-backends` in the build system interface +specification. - "tool": { - "type": "object" - } - } - } .. _pyproject-project-table: @@ -441,8 +471,51 @@ History ======= This specification was originally defined in :pep:`518` (``[build-system]`` -and ``[tool]`` tables) and :pep:`621` (``[project]`` table). +and ``[tool]`` tables), :pep:`517` (``build-backend`` and ``backend-path`` +in the ``[build-system]`` table), and :pep:`621` (``[project]`` table). + + +-------------------------------------------------------------------------- + +.. [#requires-json-schema] The following `JSON Schema `_ was + originally provided, for illustrative purposes only, and has not been + updated: + + .. code-block:: json + + { + "$schema": "http://json-schema.org/schema#", + + "type": "object", + "additionalProperties": false, + + "properties": { + "build-system": { + "type": "object", + "additionalProperties": false, + + "properties": { + "requires": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["requires"] + }, + + "tool": { + "type": "object" + } + } + } + +.. [#build-backend-optional] Historically, ``build-backend`` was defined + later than ``requires``, thus making ``build-backend`` optional is to + preserve backwards compatibility. .. _TOML: https://toml.io +.. _json-schema: https://json-schema.org