pep621.mdβ’6.56 kB
# PEP 621 Metadata
The project metadata are stored in the `pyproject.toml`. The specifications are defined by [PEP 621], [PEP 631] and [PEP 639]. Read the detailed specifications in the PEPs.
[PEP 621]: https://www.python.org/dev/peps/pep-0621/
[PEP 631]: https://www.python.org/dev/peps/pep-0631/
[PEP 639]: https://www.python.org/dev/peps/pep-0639/
_In the following part of this document, metadata should be written under `[project]` table if not given explicitly._
## Multiline description
You can split a long description onto multiple lines, thanks to TOML support for multiline strings.
Just remember to escape new lines, so the final description appears [on one line only in your package metadata](https://packaging.python.org/specifications/core-metadata/#summary).
Indentation will be removed as well when escaping new lines:
```toml
description = """\
Lorem ipsum dolor sit amet, consectetur adipiscing elit, \
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
Ut enim ad minim veniam, quis nostrud exercitation ullamco \
laboris nisi ut aliquip ex ea commodo consequat.\
"""
```
See [TOML's specification on strings](https://toml.io/en/v1.0.0#string).
## Package version
=== "Static"
```toml
[project]
version = "1.0.0"
```
=== "Dynamic"
```toml
[project]
...
dynamic = ["version"]
[tool.pdm]
version = { source = "file", path = "mypackage/__version__.py" }
```
The version will be read from the `mypackage/__version__.py` file searching for the pattern: `__version__ = "{version}"`.
Read more information about other configurations in [dynamic project version](https://backend.pdm-project.org/metadata/#dynamic-project-version) from the `pdm-backend` documentation.
## Python version
The required version of Python is specified as the string `requires-python`:
```toml
requires-python = ">=3.9"
classifiers = [
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
...
]
```
Note: As per [PEP 621](https://peps.python.org/pep-0621/#allow-tools-to-add-extend-data),
PDM is not permitted to dynamically update the `classifiers` section like some other non-compliant tools.
Thus, you should also include the appropriate [trove classifiers](https://pypi.org/classifiers/) as shown above if you plan on publishing your package on [PyPI](https://pypi.org/).
## License
<!-- TODO: update following paragraphs if PEP 639 is accepted,
see https://peps.python.org/pep-0639/#deprecate-license-classifiers -->
The license is specified as the string `license`:
```toml
license = {text = "BSD-2-Clause"}
classifiers = [
"License :: OSI Approved :: BSD License",
...
]
```
Note: As per [PEP 621](https://peps.python.org/pep-0621/#allow-tools-to-add-extend-data),
PDM is not permitted to dynamically update the `classifiers` section like some other non-compliant tools.
Thus, you should also include the appropriate [trove classifiers](https://pypi.org/classifiers/) as shown above if you plan on publishing your package on [PyPI](https://pypi.org/).
## Dependency specification
The `project.dependencies` is an array of dependency specification strings following the [PEP 440](https://www.python.org/dev/peps/pep-0440/) and [PEP 508](https://www.python.org/dev/peps/pep-0508/).
Examples:
```toml
[project]
...
dependencies = [
# Named requirement
"requests",
# Named requirement with version specifier
"flask >= 1.1.0",
# Requirement with environment marker
"pywin32; sys_platform == 'win32'",
# URL requirement
"pip @ git+https://github.com/pypa/pip.git@20.3.1"
]
```
## Optional dependencies
You can have some requirements optional, which is similar to `setuptools`' `extras_require` parameter.
```toml
[project.optional-dependencies]
socks = [ 'PySocks >= 1.5.6, != 1.5.7, < 2' ]
tests = [
'ddt >= 1.2.2, < 2',
'pytest < 6',
'mock >= 1.0.1, < 4; python_version < "3.4"',
]
```
To install a group of optional dependencies:
```bash
pdm install -G socks
```
`-G` option can be given multiple times to include more than one group.
## Context variables expansion
Depending on which build backend you are using, PDM will expand some variables in the dependency strings.
### Environment variables
=== "pdm-backend"
```toml
[project]
dependencies = ["flask @ https://${USERNAME}:${PASSWORD}/artifacts.io/Flask-1.1.2.tar.gz"]
```
=== "hatchling"
```toml
[project]
dependencies = ["flask @ https://{env:USERNAME}:{env:PASSWORD}/artifacts.io/Flask-1.1.2.tar.gz"]
```
Find more usages [here](https://hatch.pypa.io/dev/config/context/#environment-variables)
Don't worry about credential leakage, the environment variables will be expanded when needed and kept untouched in the lock file.
### Relative paths
When you add a package from a relative path, PDM will automatically save it as a relative path for `pdm-backend` and `hatchling`.
For example, if you run `pdm add ./my-package`, it will result in the following line in `pyproject.toml`.
=== "pdm-backend"
```toml
[project]
dependencies = ["my-package @ file:///${PROJECT_ROOT}/my-package"]
```
=== "hatchling"
```toml
[project]
dependencies = ["my-package @ {root:uri}/my-package"]
```
By default, hatchling doesn't support [direct references](https://hatch.pypa.io/dev/config/dependency/#direct-references)
in the dependency string, you need to turn it on in `pyproject.toml`:
```toml
[tool.hatch.metadata]
allow-direct-references = true
```
The relative path will be expanded based on the project root when installing or locking.
## Console scripts
The following content:
```toml
[project.scripts]
mycli = "mycli.__main__:main"
```
will be translated to `setuptools` style:
```python
entry_points = {
'console_scripts': [
'mycli=mycli.__main__:main'
]
}
```
Also, `[project.gui-scripts]` will be translated to `gui_scripts` entry points group in `setuptools` style.
## Entry points
Other types of entry points are given by `[project.entry-points.<type>]` section, with the same format of `[project.scripts]`:
```toml
[project.entry-points.pytest11]
myplugin = "mypackage.plugin:pytest_plugin"
```
If the entry point name contains dots or other special characters, wrap it in quotes:
```toml
[project.entry-points."flake8.extension"]
myplugin = "mypackage.plugin:flake8_plugin"
```