python projects to use pyproject.toml
@all In python 3.12 distutils
is being removed and using pyproject.toml
is
the modern way to specify a project - you can still have a setup.py
as a
configuration file but pretty much any use of python setup.py ...
has
apparently been deprecated for some time.
To learn about this I’ve updated the hatherleigh project (on a branch) to
use a pyproject.toml
. I’ve done it in a way that is compatible with running
pip install -r requirements/local.txt
or
pip install -r requirements/production.txt
but the contents of those files
have changed a bit.
pyproject.toml
is the only file needed to specify a distribution but you can
specify that it use requirements files for the dependencies - they have a
restricted syntax - no -e
or -r
lines and git repos and local apps must
have the <app name> @ <url to app>
syntax.
Essentially what that means is I’ve made the production.txt
and local.txt
files simply stubs that read other files and for the reasons outlined are
ignored by the pyproject.toml
setup.
I’ve created a dev.txt
(for development dependencies excluding the apps) and
a release.txt
(for the apps used in production), the local apps which need
to be editable installs (the -e
option) are read from a requirements file
called apps.txt
but this needs the full path to the app (and have the syntax
<app-name> @ <full path to app>
which we can’t put in the repo as that would
make it difficult to share projects.
My solution is create a apps.txt
from the release.txt
(that also has the
advantage that we only need to specify the apps once. I’ve created a branch
on toolbox make-scss-test-optional…
BTW: the branch started out as just a way to remove the new scss prompt when
using my release
script as that script processes the scss and less scripts.
Hence the obscure name) that adds an option --create-apps-txt
to kb.py
to
create this file (and added requirements/apps.txt
to .gitignore
in the
hatherleigh
project), I’ve also amended the create-venv
script in
dev-scripts
to create this file too if the project has a release.txt
file.
I’ve amended the checks on the project to check if the project uses the
pyproject.toml
file and in that case check the release.txt
file rather
than production.txt
. and since the local apps file is created from that it
does not check the local apps.
The production.txt
file now looks like::
-r base.txt
-r release.txt
local.txt
file now looks like::
-e .[dev]
-e.[dev]
installs the project using the development dependencies specified
in the pyproject.toml
file, which reads the dev dependencies from
requirements/base.txt
, requirements/apps.txt
and requirements/dev.txt
.
The new files are - release.txt::
kb-base==0.3.37
kb-block==0.2.11
kb-login==0.2.34
kb-mail==0.1.87
dev.txt::
beautifulsoup4
black
django-debug-toolbar
django-extensions
factory-boy
freezegun
GitPython
pyOpenSSL
pytest-cov
pytest-django
pytest-mock
redis-dump-load
rich
semantic-version
walkdir
Werkzeug
apps.txt (generated using ~/dev/modules/toolbox/kb.py --create-apps-txt
)
kb-base @ file:///home/patrick/dev/app/base
kb-block @ file:///home/patrick/dev/app/block
kb-login @ file:///home/patrick/dev/app/login
kb-mail @ file:///home/patrick/dev/app/mail
The pyproject.toml
already existed in the hatherleigh
project to configure
black
. Setuptools will use this file if it exists and creates the
distribution slightly differently but does not use the modern config without
a [project]
section. This parts of this file that are used by setuptools
now look like this:
[project]
name = "kb-hatherleigh"
description = "go.hatherleigh website"
dynamic = ["version", "dependencies", "readme", "authors", "classifiers", "optional-dependencies"]
[build-system]
requires = ["setuptools >= 61.0"]
build-backend = "setuptools.build_meta"
[tool.setuptools.dynamic]
dependencies = {file = ["requirements/base.txt"]}
optional-dependencies = {dev = {file = ["requirements/apps.txt", "requirements/dev.txt"]},production = {file = ["requirements/release.txt"]}}
The [build-system]
specifies setuptools needs to be greater than 61, I’m not
exactly sure that that means when using on older versions of Ubuntu. I don’t
think it is an issue because you can install the latest version of setuptools
using pip install --upgrade setuptools
. The dynamic list in the project
section essentially means those sections are created from the setup.py or as
specified in the [tools.setuptools.dynamic]
section.
To install a project for development you can use pip install -e .[dev]
or the
conventional method of pip install -r requirements/local.txt
To install in production you should be able to use
pip install <project name>[production]`
pip install -r requirements/production.txt`
We will need to change the commands that are run when we invoke
toolbox/kb.py --release
as that makes some calls to
python setup.py ...
see modernize-setup-py-project…
the changes I’ve made simply allow for the new requirements structure.
There are probably some changes we need to make to fabric as well.
I cannot see a way to make local dependencies (e.g. KB apps) editable installs
within a project using setuptools
. If changes are made to an app the only
way I can see to incorporate these is to remove the build directory in the app
and run pip install -e .[dev]
(or pip install -r requirements/local.txt
)
on the project. I’ve amended my set-branches
script to remove the build
directory from the app if the branch would be checked out.
I’ve not deployed using this yet but hopefully it should still work with the current fabric setup.
I’ll obviously test that before and wait for your feedback before merging it into the main branch.