We're upgrading to use BeeWare's Briefcase 0.3.1 for packaging, which uses pyproject.toml
instead of setup.py
to specify how to package, including which dependencies to include in a package.
Here's a minimal example of a pyproject.toml
for briefcase:
[tool.briefcase.app.exampleapp]
formal_name = "exampleapp"
description = "something"
requires = ['PyQt5', 'qtconsole']
sources = ['exampleapp']
We'd like to access the list of requires from setup.py
, so we wouldn't have to replicate it in both files, and keep them in sync. We're not ready to switch away from setuptools, this is only for packaging. The alternative is of course to let setup.py
auto-generate the pyproject.toml
file, but that seems a little backwards to the intention with PEP 518.
What is pyproject. toml? The pyproject. toml file was introduced in PEP-518 (2016) as a way of separating configuration of the build system from a specific, optional library (setuptools) and also enabling setuptools to install itself without already being installed.
Yes, pyproject. toml is the specified file format of PEP 518 which contains the build system requirements of Python projects. This solves the build-tool dependency chicken and egg problem, i.e. pip can read pyproject.
You specify them with a <key> = <value> syntax, where the key is separated from the value with an equal sign. The following is a valid TOML document with one key-value pair: greeting = "Hello, TOML!" In this example, greeting is the key, while "Hello, TOML!" is the value.
You may still find advice all over the place that involves invoking setup.py directly, but unfortunately this is no longer good advice because as of the last few years all direct invocations of setup.py are effectively deprecated in favor of invocations via purpose-built and/or standards-based CLI tools like pip, build ...
What is pyproject.toml? The pyproject.toml file was introduced in PEP-518 (2016) as a way of separating configuration of the build system from a specific, optional library (setuptools) and also enabling setuptools to install itself without already being installed.
There is a standard called PEP 621 that specifies how a project's metadata, including dependencies, should be laid out in the pyproject.toml file. Here is a list of build back-ends I know of that have support for PEP 621: For all PEP 621 compatible build back-ends, the dependencies should be written in pyproject.toml file like in the following:
To interactively create a pyproject.toml file in directory pre-existing-project: If you want to add dependencies to your project, you can specify them in the tool.poetry.dependencies section. As you can see, it takes a mapping of package names and version constraints.
It is worth noting that setup.cfg is an ini format file, and pyproject.toml is a slightly more formal ini-like format. What is pyproject.toml?
As far as I can tell, briefcase isn't actually PEP 517 compatible (at least not by default). It uses a pyproject.toml
file, but doesn't fill up the [build-system]
section, so it should be possible to set an actual PEP 517 build backend in that file without causing conflict.
pyproject.toml
[build-system]
build-backend = 'setuptools.build_meta'
requires = [
'setuptools',
'toml',
]
[tool.briefcase.app.exampleapp]
formal_name = 'exampleapp'
description = 'something'
requires = ['PyQt5', 'qtconsole']
sources = ['exampleapp']
setup.py
#!/usr/bin/env python3
import pathlib
import pkg_resources
import setuptools
import toml
def _parse_briefcase_toml(pyproject_path, app_name):
pyproject_text = pyproject_path.read_text()
pyproject_data = toml.loads(pyproject_text)
briefcase_data = pyproject_data['tool']['briefcase']
app_data = briefcase_data['app'][app_name]
setup_data = {
'name': pkg_resources.safe_name(app_data['formal_name']),
'version': briefcase_data['version'],
'install_requires': app_data['requires'],
# ...
}
return setup_data
def _setup():
app_name = 'exampleapp'
pyproject_path = pathlib.Path('pyproject.toml')
setup_data = _parse_briefcase_toml(pyproject_path, app_name)
setuptools.setup(**setup_data)
if __name__ == '__main__':
_setup()
Then pip and other PEP 517-compatible frontends should be able to build and install the project by delegating to setuptools while taking care to correctly setup a build environment containing both setuptools and toml.
I guess it would be also possible to let briefcase handle the parsing of the pyproject.toml
file (maybe with briefcase.config.parse_config(...)
) but it's not documented so I don't know how stable these APIs are.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With