Note
New in 61.0.0
Important
For the time being, pip
still might require a setup.py
file to support editable installs <pip:cli/pip_install>
.
A simple script will suffice, for example:
from setuptools import setup
setup()
Starting with 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. build
or 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 PyPUG:specifications/declaring-project-metadata
guide.
[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"
Warning
Support for declaring configurations not standardized by 621
(i.e. the [tool.setuptools]
table), is still experimental and might change in future releases.
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 /references/keywords
used by the setup.py
file, and can be set via the tool.setuptools
table:
Key | Value Type (TOML) | Notes |
---|---|---|
platforms |
array | |
|
boolean array |
If not specified, |
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 | Deprecated - Use implicit namespaces instead (420 ) |
package-data |
table/inline-table | See /userguide/datafiles |
|
boolean table/inline-table |
|
|
array of glob patterns |
Provisional - likely to change with |
data-files |
table/inline-table | Deprecated - check /userguide/datafiles |
|
array |
Deprecated - equivalent to the |
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 dict
and 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 auto-discovery
, which should cover most popular project directory organization techniques, such as the src-layout
and the 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
directive1 as shown below:
[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:
[tool.setuptools]
packages = ["my_package"]
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
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 2. For example:
# ...
[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
directive3 will read an attribute from the given module4, while file
will read the contents of all given files and concatenate them in a single string.
Key | Directive | Notes |
---|---|---|
|
|
|
description |
file |
One-line text |
classifiers |
file |
Multi-line text with one classifier per line |
|
|
INI format following |
Notes
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 fortool.setuptools.packages
, or{attr = "mymodule.attr"}
directive fortool.setuptools.dynamic.version
.↩Dynamic
scripts
andgui-scripts
are a special case. When resolving these metadata keys,setuptools
will look fortool.setuptool.dynamic.entry-points
, and use the values of theconsole_scripts
andgui_scripts
entry-point groups <PyPUG:specifications/entry-points>
.↩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 fortool.setuptools.packages
, or{attr = "mymodule.attr"}
directive fortool.setuptools.dynamic.version
.↩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 withast.literal_eval
, and should not be modified or re-assigned.↩