How to use nox with poetry?
Currently, session.install
doesn't support poetry
and install
just runs pip in the shell. You can activate poetry
with a more general method session.run
.
Example:
@nox.session(python=False)
def tests(session):
session.run('poetry', 'shell')
session.run('poetry', 'install')
session.run('pytest')
When you set up session, you can do everything by your own disabling creation of python virtualenv (python=False
) and activating poetry
's one with poetry shell
.
After some trials and errors and contrary to what I commented in @Yann's answer, it seems that poetry
ignores the VIRTUAL_ENV
variable passed by nox
.
Inspired by the wonderful series Hypermodern Python by Claudio Jolowicz, I solved the problem with the following:
@nox.session(python=PYTHON)
def test(session: Session) -> None:
"""
Run unit tests.
Arguments:
session: The Session object.
"""
args = session.posargs or ["--cov"]
session.install(".")
install_with_constraints(
session,
"coverage[toml]",
"pytest",
"pytest-cov",
"pytest-mock",
"pytest-flask",
)
session.run("pytest", *args)
Here, I'm just using pip
to install a PEP517 package.
Unfortunately PEP517 installs via pip
don't support the editable ("-e") switch.
FYI: install_with_constraints
is the function I borrowed from Claudio, edited to work on Windows:
def install_with_constraints(
session: Session, *args: str, **kwargs: Any
) -> None:
"""
Install packages constrained by Poetry's lock file.
This function is a wrapper for nox.sessions.Session.install. It
invokes pip to install packages inside of the session's virtualenv.
Additionally, pip is passed a constraints file generated from
Poetry's lock file, to ensure that the packages are pinned to the
versions specified in poetry.lock. This allows you to manage the
packages as Poetry development dependencies.
Arguments:
session: The Session object.
args: Command-line arguments for pip.
kwargs: Additional keyword arguments for Session.install.
"""
req_path = os.path.join(tempfile.gettempdir(), os.urandom(24).hex())
session.run(
"poetry",
"export",
"--dev",
"--format=requirements.txt",
f"--output={req_path}",
external=True,
)
session.install(f"--constraint={req_path}", *args, **kwargs)
os.unlink(req_path)