Projects that aren't meant to generate a wheel and `pyproject.toml`

Sorry, I thought I had for the Django case I outlined earlier.

OK, then here’s a strawman proposal…

We want something easy to write inside of single-file scripts; not too verbose while being self-explanatory to anyone reading it… We also want something that can substitute for requirements files which are used for a similar purpose for a larger grouping of Python code to cover the same use case, just at a different scale. You also want something that can help install a group of things to be used for some purpose with the code which may not directly require the code itself to be installed (e.g. linters, building the documentation).

Simple case

Top-level key named requirements which holds an array of strings representing distribution requirements to be installed (e.g. project.dependencies, but at the top-level for the file).

We can do the same for requires-python.

This covers the PEP 723 case (although it isn’t meant to be exclusive to single-file scripts). It’s short and to the point if you needs are simple.

requires-python = ">=3.10"
requirements = ["requests", "rich"]

Complex case

A [requirements] table of arrays of strings (e.g. project.optional-dependencies).

To refer to another key, use either .[key] or simply [key] (I personally don’t care which format, but the former has some precedence thanks to pip install -e). That gets you the equivalent of -r from requirements files.

This covers the requirements file case where you have multiple configurations which may or may not be related. I’m personally not concerned about specifying different requirements for different Python versions as markers handle that along with requires-python.

Since you already need to use -r with pip install to read in requirements files I don’t think it’s too much of a burden to skip the default requirement group name for now (although I bet it becomes “default” by convention really quickly), but I do think it will eventually come up.

requires-python = ">=3.10"

[requirements]
default = ["requests", "rich"]
test = [".[default]", "pytest"]  # Notice how it requires "default".
lint = ["ruff"]
docs = ["sphinx", "Furo"]

This still leaves the door open for external lock files since you would be able to specify what requirement group(s) you wanted to be locked.

11 Likes