Open henryiii opened 5 months ago
PEP 735 seems relevant too. The proposed solution would allow installing dependency groups, if that PEP gets accepted.
What about nox.toml.load
as the name? That would leave the namespace open for future helpers to get dependency groups (for example). You can support PEP 735 with the current toml load function, but a user would have to implement the 'include' feature manually; I think having a helper to load it would make sense if it gets accepted.
I like the idea of creating a namespace.
Bike shedding: I'm not sure about the name TOML, it's just a format. Can we come up with a name that expresses what we are loading? Is it a Python project configuration? In which case, nox.project.load
seems appropriate. (I always feel that pyproject
is a bit redundant when you're already in Python. But no strong opinion here.)
Slightly OT but I've been pondering if a nox.project.build
primitive would let us tackle #740
I was assuming build
would need to be a session method, since it needs the current Python to build with. It would need to be able to cache between sessions, but it would need to start with the current's session's Python. And it would ideally also respect the venv setting (at least uv vs. virtualenv). However, I suppose it could be standalone and just take the python version and venv mode. It doesn't need the session's virtualenv itself.
nox.project
isn't as clearly pyproject.toml
related; I could see someone thinking it loads some sort of nox project, like trying to load noxfile.py
somehow. pyproject.toml needed the py in it because other tooling (like Rust's Cargo) also use toml.
I think it would be good to think about possible future additions, and see which they would make the most sense in. If there was a build
, nox.pyproject.build
is nice for how it mirrors pyproject-build
, the command pypa/build
installs.
Regardless of project
vs. pyproject
, how about going back to the load_toml
name in the namespace? The function itself does load toml - either a .toml
file or embedded toml in .py
files via PEP 723.
Edit: thinking a bit more about it, I think nox.project
is okay. It might eventually contain things not specifically tied to the pyproject.toml, and is more about managing a project, I think. But still fine with either one, I used project
in the PR for now.
I think #631 would be a good step for build, hopefully that can be revived in the future. I wasn't planning on doing much for build until that was worked on.
I've been finding a helper like this to be very useful:
def install_and_run(session: nox.Session, script: str, *args: str, **kwargs: Any) -> str | None:
deps = nox.project.load_toml(script)["dependencies"]
session.install(*deps)
return session.run("python", script, *args, **kwargs)
Typing it is non-trivial, as it really should wrap session.run. Would making something like this available on session
(with the install part being skipped if the script doesn't have PEP 723 dependencies) be a useful next step? What would the function be called? install_and_run_python_script
is a bit too long. ;)
How would this feature be useful?
I'd love to have good support for PEP 723 in nox. As a reminder, scripts can start with this:
(I wrote a post about it a while back, see here. I've started adding this to helper scripts; but most of the time I also have nox sessions that run the helper scripts, and it's nice to have then all in once place and show up with
nox -l
, and I'd like to keep the canonical dependency list inside the script.Now, being written in Python, you could implement this yourself in a noxfile - except if nox runs on Python < 3.11, no TOML library is installed (this hits me a lot - since I also often need to pull dependency lists from pyproject.toml, too, which can't be done since nox doesn't provide
tomli
on Python < 3.11 - I've really wanted it to for a while now).Describe the solution you'd like
I thought about a lot of ways, and there is a simple solution that could be built upon later, but provides a lot of flexibility and utility for now. A new function could be added,
nox.project.load_toml
(happy to bike shed on name). This would take a path to either a toml file (which it would load) or a python file, which it would load the/// script
block. The example above then would be:And you could use it to for example install a project's dependencies without building the project:
(you could modify this for Poetry, as well) You can't do this today unless you assume nox will always run on Python 3.11 or above.
You could also access
requires-python
too, though nox can't do much with it yet. Might be a future addition, though, to allow Python to be specified as a SpecifierSet.Describe alternatives you've considered
I've thought about a lot of different ways, and finally arrived on the one above. A few of them were:
We could provide a way to turn a script into a session. This might look like this:
The problem is that this is quite rigid; if you want to add anything, like logging or something, you can't easily make this a normal session without something like proposed above. This could come later, but wouldn't be a good starting point.
We could provide a
file=
argument to install. This would mean thatsession.install(file="myscript.py")
would install the dependencies in myscript.py. You could also use it for requirements.txt; not that helpful, but nice. The problem comes when usingfile="pyproject.toml"
, as there's no way to specify extras. Adding another keyword argument that only worked for pyproject.toml files seems like poor design, and would theextras=
keyword also installproject.dependencies
? And in both cases, some people might also expect this to install the project itself, which wouldn't be helpful (you can just install"."
for that), but it's not clear by the design. We could support Poetry transparently, which is nice. And this might be nice for supporting conda (in conda_install). But the issues above are big downsides. And it doesn't provide a way to get other information, likerequires-python
.A variation of the above idea would be a
.get_deps()
method that read a file and produced a list of deps that the user could then pass toinstall
, or do something else with. This has many of the same drawbacks though.Anything else?
Name ideas:
nox.load_pyproject
nox.load_toml
nox.load_config
Edit: using current proposal of
nox.project.load_toml
.