-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support installing Poetry dependency groups #663
Comments
May be a duplicate of |
@thedrow You mentioned at python-poetry/poetry#1856 (comment) wanting to use Poetry dependency groups with |
Yup. Exactly. |
This would be useful for my projects. I can start a PR if there's interest. |
@edgarrmondragon Go ahead :) |
So I think this would be a relatively easy way to get a |
Thinking about this some more, perhaps a better API for this that would allow users to mix the current functionality with groups in a single command could use a name-only argument: def test(session: nox_poetry.Session):
session.install(".", "pytest", poetry_groups=["lint", "type_check"]) That way a single command can used locked dependencies from any source available. |
If you have dependency groups, why not use plain Nox with a small helper like this? I'd be curious what value you see in nox-poetry given that you can now easily install locked dependency groups using just Nox and Poetry >=1.2? |
@cjolowicz I'm probably missing something from your example but how do you ensure that |
Poetry honors the (At least, it did when I wrote this code 😅 ) |
The first time I tried this (on Windows with latest Poetry/Nox) using the # noxfile.py
...
@session
def fmt(s: Session) -> None:
install(s, groups=["fmt"], root=False)
s.run("isort", ".")
s.run("black", ".") It started to remove a bunch of packages in the outer environment due to
I think this demonstrates that relying on |
I like nox-poetry's workflow of exporting requirements and then installing them with pip, I don't want to install with poetry directly into my nox sessions. For now I'm just copy/pasting a basic helper function to handle installs:
But it would be nice to have that logic handled in a common package, and it seems like nox-poetry is a good candidate to house it. My copy/paste function doesn't have nox-poetry's test coverage or nice "Warning:" message filter, so for me there's value to using it. But to your point, my current workflow is to just use plain nox with a helper function. |
That was my thought as well. We have dozens of Poetry/Nox projects and having a shared package where we know others are also collaborating/testing/etc. has been a great way to avoid code duplication and engage with others using a similar workflow. For that |
This looks like a Poetry bug. Can you provide instructions to reproduce this? To my knowledge, pip install pipx
pipx install poetry
export PATH=$HOME/.local/bin:$PATH
poetry new project
cd project
poetry add -G test pytest
poetry add -G docs sphinx
python -m venv /tmp/venv
. /tmp/venv/bin/activate
poetry install --sync --only docs
deactivate
poetry install You should see Poetry install the docs group into the virtual environment. Outside the virtual environment, the last |
[tool.poetry]
name = "poetry-test"
version = "0.1.0"
description = ""
authors = []
readme = "README.md"
packages = [{include = "poetry_test"}]
[tool.poetry.dependencies]
python = "^3.10"
pydantic = "*"
[tool.poetry.group.nox.dependencies]
nox = "*"
[tool.poetry.group.fmt.dependencies]
black = "*"
isort = "*"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api" from typing import Iterable
import nox
def install(session: nox.Session, *, groups: Iterable[str], root: bool = True) -> None:
"""Install the dependency groups using Poetry.
This function installs the given dependency groups into the session's
virtual environment. When ``root`` is true (the default), the function
also installs the root package and its default dependencies.
To avoid an editable install, the root package is not installed using
``poetry install``. Instead, the function invokes ``pip install .``
to perform a PEP 517 build.
Args:
session: The Session object.
groups: The dependency groups to install.
root: Install the root package.
"""
session.run_always(
"poetry",
"install",
"--no-root",
"--sync",
"--{}={}".format("only" if not root else "with", ",".join(groups)),
external=True,
)
if root:
session.install(".")
@nox.session
def fmt(s: nox.Session) -> None:
install(s, groups=["fmt"], root=False)
s.run("isort", ".")
s.run("black", ".") > poetry install --sync
> poetry shell
(poetry-test-py3.10) > nox -s fmt
nox > Running session fmt
nox > Creating virtual environment (virtualenv) using python.exe in .nox\fmt
nox > poetry install --no-root --sync --only=fmt
Installing dependencies from lock file
Package operations: 0 installs, 0 updates, 8 removals
• Removing argcomplete (2.0.0)
• Removing colorlog (6.7.0)
• Removing distlib (0.3.6)
• Removing filelock (3.9.0)
• Removing nox (2022.11.21)
...
PermissionError: [WinError 5] Access is denied: The So note that
|
@johnthagen Does this reproduce when you don't have Nox as a development dependency? I recommend installing both Nox and Poetry using pipx, side by side. You're running Nox from a Poetry environment, and then Poetry from a Nox environment. Theoretically, it should work, but it's unneeded complexity IMO. I'd also avoid constraining the dependency tree of your application with tools that can be part of the global dev environment. FWIW, I tried your example in a Windows runner on GHA, but it didn't reproduce in that environment. Here's an example run: https://github.com/cjolowicz/poetry-test/actions/runs/4801627813/jobs/8544094456 |
In our case, we want to lock the exact version of Nox (and nox-poetry) because it is part of our CI process and thus we want it to be reproducible. In my experience it also simplifies the setup for each dev if when they run
I don't disagree in principle (perhaps one day Hatch or something like it can replace the need for Poetry and put everything in its own environment), but for now to make the workflow simple using Poetry (which chooses to lock everything together) and reproducible we are already constraining our environment with a host of other tools we need to lock and have reproducible versions (mypy, pytest, black, isort, ruff, etc.). |
A concrete example in recent past of why it's important to pin Nox is when Nox changed its behaviour in the presence of the Without Nox being pinned, this would have broken CI builds that depended on the previous behaviour. An example fix: So our teams insist on locking as much of the development tools as possible and keeping both developer tools and CI in sync because things like this are bound to come up as FOSS projects evolve. |
Just wanted to share a workaround i'm using to parse the toml for the groups from typing import List
from pathlib import Path
import toml
def install_dependency_groups(session, groups: List[str] = []):
"""Manually parse the pyproject file to find group(s) of dependencies, then install."""
pyproject_path = Path("pyproject.toml")
data = toml.load(pyproject_path)
all_dependencies = []
for group in groups:
dependencies = data.get("tool", {}).get("poetry", {}).get("group", {}).get(group, {}).get("dependencies", {})
all_dependencies += list(dependencies.keys())
all_dependencies = list(set(all_dependencies))
session.install(*all_dependencies)
...
install_dependency_groups(session, groups=["lint", "tests"]) |
Nox data = nox.project.load_toml(pyproject_path) https://nox.thea.codes/en/stable/tutorial.html#loading-dependencies-from-pyproject-toml-or-scripts So, one fewer import 😅 |
I improve the previous workaround to install extras from pyproject.toml:
In noxfile.py:
|
Poetry 1.2
will be addingadded support for dependency groups. It would be ergonomic if you could install a dependency group (as a whole) into anox
session.Consider a Poetry group:
The cooresponding
nox
session could be simplified to:This avoids the DRY problem of listing all of the lint dependencies twice, once in a Poetry group and again in a
nox
session.Related to
The text was updated successfully, but these errors were encountered: