I’m mentally looking at this conversation as seeing if we can write down some of the inputs we give a resolver, e.g., requirements.in
if you’re viewing this from a pip-compile
perspective.
What sort of data are we talking about?
What are the inputs to a resolver to calculate the dependency graph (and we can use pip’s resolver as the running example)?
- Requirements
- Constraints
- Places to look for the dependencies
- Platform details (i.e., supported wheel tags, which implicitly includes Python version, interpreter, OS, and CPU architecture)
- Stuff like requiring wheels
The bare minimum that a resolver needs is:
- Requirements
Pip’s requirements files cover:
- Requirements (which can refer to other requirements in other files)
- Constraints (which must be in an external file)
- Places to look for dependencies
What can be inferred is:
- Places to look for the dependencies: assume PyPI
- Platform details: assume the running Python interpreter
When you’re sharing code with others, the constants of your code that you can reliably write down regardless of your situation is:
- Requirements
- Python version support
I’m assuming constraints are situation-dependent.
Strawman proposal
With all of that in mind, my strawman proposal is a [run]
table that supports three keys:
requires-python
dependencies
dev-dependencies
I think the first two are self-explanatory. The third would be like project.optional-dependencies
. It might be nice to come up with a way to handle inheriting from other dev-dependencies
entries, e.g. anything in just square brackets automatically includes that dev-dependencies
entry. So having coverage = ["[tests]", "coverage"]
would include everything in run.dev-dependencies.tests
as well as "coverage"
. Or you could make it .[tests]
. I realize this isn’t currently supported in any spec right now, but I think it would help with the case where people build up dependencies using -r
in requirements files, and so something to include in the PEP (or a separate PEP worth writing since without a name you can’t use the self-referential hack to get extras to refer to each other, e.g. in a project named spam
, use coverage = ["spam[tests]", "coverage"]
).
As written, this could go into pyproject.toml
. I’m not sure if people need more flexibility in how to write out various dependency structures like you can with -r
in requirements files and thus require some more sophisticated structure (i.e., a way to specify independent top-level requirements that are in no way associated with each other), or even separate files.
I’m personally okay viewing constraints and package indexes as something you pass in to the installer when calling them instead of embedding them in the [run]
table.