1.. _pyproject.toml config: 2 3----------------------------------------------------- 4Configuring setuptools using ``pyproject.toml`` files 5----------------------------------------------------- 6 7.. note:: New in 61.0.0 (**experimental**) 8 9.. warning:: 10 Support for declaring :doc:`project metadata 11 <PyPUG:specifications/declaring-project-metadata>` or configuring 12 ``setuptools`` via ``pyproject.toml`` files is still experimental and might 13 change (or be removed) in future releases. 14 15.. important:: 16 For the time being, ``pip`` still might require a ``setup.py`` file 17 to support :doc:`editable installs <pip:cli/pip_install>`. 18 19 A simple script will suffice, for example: 20 21 .. code-block:: python 22 23 from setuptools import setup 24 25 setup() 26 27Starting with :pep:`621`, the Python community selected ``pyproject.toml`` as 28a standard way of specifying *project metadata*. 29``Setuptools`` has adopted this standard and will use the information contained 30in this file as an input in the build process. 31 32The example below illustrates how to write a ``pyproject.toml`` file that can 33be used with ``setuptools``. It contains two TOML tables (identified by the 34``[table-header]`` syntax): ``build-system`` and ``project``. 35The ``build-system`` table is used to tell the build frontend (e.g. 36:pypi:`build` or :pypi:`pip`) to use ``setuptools`` and any other plugins (e.g. 37``setuptools-scm``) to build the package. 38The ``project`` table contains metadata fields as described by 39:doc:`PyPUG:specifications/declaring-project-metadata` guide. 40 41.. _example-pyproject-config: 42 43.. code-block:: toml 44 45 [build-system] 46 requires = ["setuptools", "setuptools-scm"] 47 build-backend = "setuptools.build_meta" 48 49 [project] 50 name = "my_package" 51 description = "My package description" 52 readme = "README.rst" 53 keywords = ["one", "two"] 54 license = {text = "BSD 3-Clause License"} 55 classifiers = [ 56 "Framework :: Django", 57 "Programming Language :: Python :: 3", 58 ] 59 dependencies = [ 60 "requests", 61 'importlib-metadata; python_version<"3.8"', 62 ] 63 dynamic = ["version"] 64 65 [project.optional-dependencies] 66 pdf = ["ReportLab>=1.2", "RXP"] 67 rest = ["docutils>=0.3", "pack ==1.1, ==1.3"] 68 69 [project.scripts] 70 my-script = "my_package.module:function" 71 72 73.. _setuptools-table: 74 75Setuptools-specific configuration 76================================= 77 78While the standard ``project`` table in the ``pyproject.toml`` file covers most 79of the metadata used during the packaging process, there are still some 80``setuptools``-specific configurations that can be set by users that require 81customization. 82These configurations are completely optional and probably can be skipped when 83creating simple packages. 84They are equivalent to the :doc:`/references/keywords` used by the ``setup.py`` 85file, and can be set via the ``tool.setuptools`` table: 86 87========================= =========================== ========================= 88Key Value Type (TOML) Notes 89========================= =========================== ========================= 90``platforms`` array 91``zip-safe`` boolean If not specified, ``setuptools`` will try to guess 92 a reasonable default for the package 93``eager-resources`` array 94``py-modules`` array See tip below 95``packages`` array or ``find`` directive See tip below 96``package-dir`` table/inline-table Used when explicitly listing ``packages`` 97``namespace-packages`` array Not necessary if you use :pep:`420` 98``package-data`` table/inline-table See :doc:`/userguide/datafiles` 99``include-package-data`` boolean ``True`` by default 100``exclude-package-data`` table/inline-table 101``license-files`` array of glob patterns **Provisional** - likely to change with :pep:`639` 102 (by default: ``['LICEN[CS]E*', 'COPYING*', 'NOTICE*', 'AUTHORS*']``) 103``data-files`` table/inline-table **Deprecated** - check :doc:`/userguide/datafiles` 104``script-files`` array **Deprecated** - equivalent to the ``script`` keyword in ``setup.py`` 105 (should be avoided in favour of ``project.scripts``) 106``provides`` array **Ignored by pip** 107``obsoletes`` array **Ignored by pip** 108========================= =========================== ========================= 109 110.. note:: 111 The `TOML value types`_ ``array`` and ``table/inline-table`` are roughly 112 equivalent to the Python's :obj:`dict` and :obj:`list` data types. 113 114Please note that some of these configurations are deprecated or at least 115discouraged, but they are made available to ensure portability. 116New packages should avoid relying on deprecated/discouraged fields, and 117existing packages should consider alternatives. 118 119.. tip:: 120 When both ``py-modules`` and ``packages`` are left unspecified, 121 ``setuptools`` will attempt to perform :ref:`auto-discovery`, which should 122 cover most popular project directory organization techniques, such as the 123 :ref:`src-layout` and the :ref:`flat-layout`. 124 125 However if your project does not follow these conventional layouts 126 (e.g. you want to use a ``flat-layout`` but at the same time have custom 127 directories at the root of your project), you might need to use the ``find`` 128 directive [#directives]_ as shown below: 129 130 .. code-block:: toml 131 132 [tool.setuptools.packages.find] 133 where = ["src"] # list of folders that contain the packages (["."] by default) 134 include = ["my_package*"] # package names should match these glob patterns (["*"] by default) 135 exclude = ["my_package.tests*"] # exclude packages matching these glob patterns (empty by default) 136 namespaces = false # to disable scanning PEP 420 namespaces (true by default) 137 138 Note that the glob patterns in the example above need to be matched 139 by the **entire** package name. This means that if you specify ``exclude = ["tests"]``, 140 modules like ``tests.my_package.test1`` will still be included in the distribution 141 (to remove them, add a wildcard to the end of the pattern: ``"tests*"``). 142 143 Alternatively, you can explicitly list the packages in modules: 144 145 .. code-block:: toml 146 147 [tool.setuptools] 148 packages = ["my_package"] 149 150 151.. _dynamic-pyproject-config: 152 153Dynamic Metadata 154================ 155 156Note that in the first example of this page we use ``dynamic`` to identify 157which metadata fields are dynamically computed during the build by either 158``setuptools`` itself or the plugins installed via ``build-system.requires`` 159(e.g. ``setuptools-scm`` is capable of deriving the current project version 160directly from the ``git`` :wiki:`version control` system). 161 162Currently the following fields can be listed as dynamic: ``version``, 163``classifiers``, ``description``, ``entry-points``, ``scripts``, 164``gui-scripts`` and ``readme``. 165When these fields are expected to be provided by ``setuptools`` a 166corresponding entry is required in the ``tool.setuptools.dynamic`` table 167[#entry-points]_. For example: 168 169.. code-block:: toml 170 171 # ... 172 [project] 173 name = "my_package" 174 dynamic = ["version", "readme"] 175 # ... 176 [tool.setuptools.dynamic] 177 version = {attr = "my_package.VERSION"} 178 readme = {file = ["README.rst", "USAGE.rst"]} 179 180In the ``dynamic`` table, the ``attr`` directive [#directives]_ will read an 181attribute from the given module [#attr]_, while ``file`` will read the contents 182of all given files and concatenate them in a single string. 183 184================= =================== ========================= 185Key Directive Notes 186================= =================== ========================= 187``version`` ``attr``, ``file`` 188``readme`` ``file`` 189``description`` ``file`` One-line text 190``classifiers`` ``file`` Multi-line text with one classifier per line 191``entry-points`` ``file`` INI format following :doc:`PyPUG:specifications/entry-points` 192 (``console_scripts`` and ``gui_scripts`` can be included) 193================= =================== ========================= 194 195---- 196 197.. rubric:: Notes 198 199.. [#entry-points] Dynamic ``scripts`` and ``gui-scripts`` are a special case. 200 When resolving these metadata keys, ``setuptools`` will look for 201 ``tool.setuptool.dynamic.entry-points``, and use the values of the 202 ``console_scripts`` and ``gui_scripts`` :doc:`entry-point groups 203 <PyPUG:specifications/entry-points>`. 204 205.. [#directives] In the context of this document, *directives* are special TOML 206 values that are interpreted differently by ``setuptools`` (usually triggering an 207 associated function). Most of the times they correspond to a special TOML table 208 (or inline-table) with a single top-level key. 209 For example, you can have the ``{find = {where = ["src"], exclude=["tests*"]}}`` 210 directive for ``tool.setuptools.packages``, or ``{attr = "mymodule.attr"}`` 211 directive for ``tool.setuptools.dynamic.version``. 212 213.. [#attr] ``attr`` is meant to be used when the module attribute is statically 214 specified (e.g. as a string, list or tuple). As a rule of thumb, the 215 attribute should be able to be parsed with :func:`ast.literal_eval`, and 216 should not be modified or re-assigned. 217 218.. _TOML value types: https://toml.io/en/v1.0.0 219