.. _pyproject.toml config: ----------------------------------------------------- Configuring setuptools using ``pyproject.toml`` files ----------------------------------------------------- .. note:: New in 61.0.0 (**experimental**) .. warning:: Support for declaring :doc:`project metadata ` or configuring ``setuptools`` via ``pyproject.toml`` files is still experimental and might change (or be removed) in future releases. .. important:: For the time being, ``pip`` still might require a ``setup.py`` file to support :doc:`editable installs `. A simple script will suffice, for example: .. code-block:: python from setuptools import setup setup() Starting with :pep:`621`, the Python community selected ``pyproject.toml`` as a standard way of specifying *project metadata*. ``Setuptools`` has adopted this standard and will use the information contained in this file as an input in the build process. The example below illustrates how to write a ``pyproject.toml`` file that can be used with ``setuptools``. It contains two TOML tables (identified by the ``[table-header]`` syntax): ``build-system`` and ``project``. The ``build-system`` table is used to tell the build frontend (e.g. :pypi:`build` or :pypi:`pip`) to use ``setuptools`` and any other plugins (e.g. ``setuptools-scm``) to build the package. The ``project`` table contains metadata fields as described by :doc:`PyPUG:specifications/declaring-project-metadata` guide. .. _example-pyproject-config: .. code-block:: toml [build-system] requires = ["setuptools", "setuptools-scm"] build-backend = "setuptools.build_meta" [project] name = "my_package" description = "My package description" readme = "README.rst" keywords = ["one", "two"] license = {text = "BSD 3-Clause License"} classifiers = [ "Framework :: Django", "Programming Language :: Python :: 3", ] dependencies = [ "requests", 'importlib-metadata; python_version<"3.8"', ] dynamic = ["version"] [project.optional-dependencies] pdf = ["ReportLab>=1.2", "RXP"] rest = ["docutils>=0.3", "pack ==1.1, ==1.3"] [project.scripts] my-script = "my_package.module:function" .. _setuptools-table: Setuptools-specific configuration ================================= While the standard ``project`` table in the ``pyproject.toml`` file covers most of the metadata used during the packaging process, there are still some ``setuptools``-specific configurations that can be set by users that require customization. These configurations are completely optional and probably can be skipped when creating simple packages. They are equivalent to the :doc:`/references/keywords` used by the ``setup.py`` file, and can be set via the ``tool.setuptools`` table: ========================= =========================== ========================= Key Value Type (TOML) Notes ========================= =========================== ========================= ``platforms`` array ``zip-safe`` boolean If not specified, ``setuptools`` will try to guess a reasonable default for the package ``eager-resources`` array ``py-modules`` array See tip below ``packages`` array or ``find`` directive See tip below ``package-dir`` table/inline-table Used when explicitly listing ``packages`` ``namespace-packages`` array Not necessary if you use :pep:`420` ``package-data`` table/inline-table See :doc:`/userguide/datafiles` ``include-package-data`` boolean ``True`` by default ``exclude-package-data`` table/inline-table ``license-files`` array of glob patterns **Provisional** - likely to change with :pep:`639` (by default: ``['LICEN[CS]E*', 'COPYING*', 'NOTICE*', 'AUTHORS*']``) ``data-files`` table/inline-table **Deprecated** - check :doc:`/userguide/datafiles` ``script-files`` array **Deprecated** - equivalent to the ``script`` keyword in ``setup.py`` (should be avoided in favour of ``project.scripts``) ``provides`` array **Ignored by pip** ``obsoletes`` array **Ignored by pip** ========================= =========================== ========================= .. note:: The `TOML value types`_ ``array`` and ``table/inline-table`` are roughly equivalent to the Python's :obj:`dict` and :obj:`list` data types. Please note that some of these configurations are deprecated or at least discouraged, but they are made available to ensure portability. New packages should avoid relying on deprecated/discouraged fields, and existing packages should consider alternatives. .. tip:: When both ``py-modules`` and ``packages`` are left unspecified, ``setuptools`` will attempt to perform :ref:`auto-discovery`, which should cover most popular project directory organization techniques, such as the :ref:`src-layout` and the :ref:`flat-layout`. However if your project does not follow these conventional layouts (e.g. you want to use a ``flat-layout`` but at the same time have custom directories at the root of your project), you might need to use the ``find`` directive [#directives]_ as shown below: .. code-block:: toml [tool.setuptools.packages.find] where = ["src"] # list of folders that contain the packages (["."] by default) include = ["my_package*"] # package names should match these glob patterns (["*"] by default) exclude = ["my_package.tests*"] # exclude packages matching these glob patterns (empty by default) namespaces = false # to disable scanning PEP 420 namespaces (true by default) Note that the glob patterns in the example above need to be matched by the **entire** package name. This means that if you specify ``exclude = ["tests"]``, modules like ``tests.my_package.test1`` will still be included in the distribution (to remove them, add a wildcard to the end of the pattern: ``"tests*"``). Alternatively, you can explicitly list the packages in modules: .. code-block:: toml [tool.setuptools] packages = ["my_package"] .. _dynamic-pyproject-config: Dynamic Metadata ================ Note that in the first example of this page we use ``dynamic`` to identify which metadata fields are dynamically computed during the build by either ``setuptools`` itself or the plugins installed via ``build-system.requires`` (e.g. ``setuptools-scm`` is capable of deriving the current project version directly from the ``git`` :wiki:`version control` system). Currently the following fields can be listed as dynamic: ``version``, ``classifiers``, ``description``, ``entry-points``, ``scripts``, ``gui-scripts`` and ``readme``. When these fields are expected to be provided by ``setuptools`` a corresponding entry is required in the ``tool.setuptools.dynamic`` table [#entry-points]_. For example: .. code-block:: toml # ... [project] name = "my_package" dynamic = ["version", "readme"] # ... [tool.setuptools.dynamic] version = {attr = "my_package.VERSION"} readme = {file = ["README.rst", "USAGE.rst"]} In the ``dynamic`` table, the ``attr`` directive [#directives]_ will read an attribute from the given module [#attr]_, while ``file`` will read the contents of all given files and concatenate them in a single string. ================= =================== ========================= Key Directive Notes ================= =================== ========================= ``version`` ``attr``, ``file`` ``readme`` ``file`` ``description`` ``file`` One-line text ``classifiers`` ``file`` Multi-line text with one classifier per line ``entry-points`` ``file`` INI format following :doc:`PyPUG:specifications/entry-points` (``console_scripts`` and ``gui_scripts`` can be included) ================= =================== ========================= ---- .. rubric:: Notes .. [#entry-points] Dynamic ``scripts`` and ``gui-scripts`` are a special case. When resolving these metadata keys, ``setuptools`` will look for ``tool.setuptool.dynamic.entry-points``, and use the values of the ``console_scripts`` and ``gui_scripts`` :doc:`entry-point groups `. .. [#directives] In the context of this document, *directives* are special TOML values that are interpreted differently by ``setuptools`` (usually triggering an associated function). Most of the times they correspond to a special TOML table (or inline-table) with a single top-level key. For example, you can have the ``{find = {where = ["src"], exclude=["tests*"]}}`` directive for ``tool.setuptools.packages``, or ``{attr = "mymodule.attr"}`` directive for ``tool.setuptools.dynamic.version``. .. [#attr] ``attr`` is meant to be used when the module attribute is statically specified (e.g. as a string, list or tuple). As a rule of thumb, the attribute should be able to be parsed with :func:`ast.literal_eval`, and should not be modified or re-assigned. .. _TOML value types: https://toml.io/en/v1.0.0