How do I read project dependencies from pyproject.toml from my setup.py, to avoid duplicating the information in both files?
Asked Answered
E

1

9

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.

Eulau answered 13/6, 2020 at 16:33 Comment(2)
I don't know much about briefcase, but I would assume that no setup.py file at all is required. Maybe better chances over there: beeware.org/community/getting-helpCurd
If you want to keep both setup.py and pyproject.toml, I guess you could write a bit of code in setup.py that parses the Toml file, but then setup.py needs an external dependency on a Toml library (since there is no Toml parser in Python's standard library). Seems like it could be feasible somehow (maybe with some compromise).Curd
C
8

This answer might be outdated. I do not have time to investigate right now. I recommend checking the briefcase resources for more up-to-date information. For example this section of the doc might be relevant: https://briefcase.readthedocs.io/en/latest/reference/configuration.html#pep621-compatibility


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.

Curd answered 14/6, 2020 at 12:0 Comment(1)
I like toml.load(pyproject_path.open()) for reading the fileKoine

© 2022 - 2024 — McMap. All rights reserved.