Poetry2nix flake
README.md
poetry2nix turns Poetry projects into Nix derivations without the need to actually write Nix expressions. It does so by parsing pyproject.toml
and poetry.lock
and converting them to Nix derivations on the fly.
For more information, see the announcement post on the Tweag blog.
The poetry2nix public API consists of the following attributes:
poetry.lock
.tool.poetry.scripts
of the pyproject.toml
.Creates a Python application using the Python interpreter specified based on the designated poetry project and lock files. mkPoetryApplication
takes an attribute set with the following attributes (attributes without default are mandatory):
cleanPythonSources { src = projectDir; }
).pyproject.toml
(default: projectDir + "/pyproject.toml"
).poetry.lock
file path (default: projectDir + "/poetry.lock"
).[defaultPoetryOverrides]
).{}
).pkgs.python3
).false
).[ ]
).extras
to install (default: [ "*" ]
, all extras).Other attributes are passed through to buildPythonApplication
.
poetry2nix.mkPoetryApplication {
projectDir = ./.;
}
See ./pkgs/poetry/default.nix for a working example.
The resulting derivation also has the passthru attribute dependencyEnv
, which is an environment with a python interpreter, all non-development dependencies and your application. This can be used if your application doesn't provide any binaries on its own and instead relies on dependencies binaries to call its modules (as is often the case with celery
or gunicorn
). For example, if your application defines a CLI for the module admin
and a gunicorn app for the module web
, a working default.nix
would contain
let
app = poetry2nix.mkPoetryApplication {
projectDir = ./.;
};
in app.dependencyEnv
After building this expression, your CLI and app can be called with these commands
$ result/bin/python -m admin
$ result/bin/gunicorn web:app
Note: If you need to perform overrides on the application, use app.dependencyEnv.override { app = app.override { ... }; }
. See ./tests/dependency-environment/default.nix for a full example.
Creates an environment that provides a Python interpreter along with all dependencies declared by the designated poetry project and lock files. Also allows package sources of an application to be installed in editable mode for fast development. mkPoetryEnv
takes an attribute set with the following attributes (attributes without default are mandatory):
pyproject.toml
(default: projectDir + "/pyproject.toml"
).poetry.lock
file path (default: projectDir + "/poetry.lock"
).[defaultPoetryOverrides]
).pkgs.python3
).develop = true
will be installed in editable mode unless explicitly passed to editablePackageSources
as null
. (default:{}
).pyproject.toml
that you still want to include. An example of such a package may be pip
. (default:(ps: [ ])
).false
).[ "dev" ]
).extras
to install (default: [ "*" ]
, all extras).poetry2nix.mkPoetryEnv {
projectDir = ./.;
}
See ./tests/env/default.nix for a working example.
poetry2nix.mkPoetryEnv {
projectDir = ./.;
editablePackageSources = {
my-app = ./src;
};
}
See ./tests/editable/default.nix for a working example of an editable package.
The env
attribute of the attribute set created by mkPoetryEnv
contains a shell environment.
{ pkgs ? import <nixpkgs> {} }:
let
myAppEnv = pkgs.poetry2nix.mkPoetryEnv {
projectDir = ./.;
editablePackageSources = {
my-app = ./src;
};
};
in myAppEnv.env
For a shell environment including external dependencies, override the env
to add dependency packages (for example, pkgs.hello
) as build inputs.
{ pkgs ? import <nixpkgs> {} }:
let
myAppEnv = pkgs.poetry2nix.mkPoetryEnv {
projectDir = ./.;
editablePackageSources = {
my-app = ./src;
};
};
in myAppEnv.env.overrideAttrs (oldAttrs: {
buildInputs = [ pkgs.hello ];
})
Creates an attribute set of the shape { python, poetryPackages, pyProject, poetryLock }
. Where python
is the interpreter specified, poetryPackages
is a list of all generated python packages, pyProject
is the parsed pyproject.toml
and poetryLock
is the parsed poetry.lock
file. mkPoetryPackages
takes an attribute set with the following attributes (attributes without default are mandatory):
pyproject.toml
(default: projectDir + "/pyproject.toml"
).poetry.lock
file path (default: projectDir + "/poetry.lock"
).[defaultPoetryOverrides]
).pkgs.python3
).{}
).false
).[ ]
).extras
to install (default: [ "*" ]
, all extras).poetry2nix.mkPoetryPackages {
projectDir = ./.;
python = python35;
}
Creates a package containing the scripts from tool.poetry.scripts
of the pyproject.toml
:
pyproject.toml
(default: projectDir + "/pyproject.toml"
).pkgs.python3
).poetry2nix.mkPoetryScriptsPackage {
projectDir = ./.;
python = python35;
}
Creates a package containing editable sources. Changes in the specified paths will be reflected in an interactive nix-shell session without the need to restart it:
pyproject.toml
(default: projectDir + "/pyproject.toml"
).pkgs.python3
).{}
).poetry2nix.mkPoetryEditablePackage {
projectDir = ./.;
python = python35;
editablePackageSources = {
my-app = ./src;
};
}
poetry2nix bundles a set of default overrides that fix problems with various Python packages. These overrides are implemented in overrides.
Returns a list containing the specified overlay and defaultPoetryOverrides
.
Takes an attribute set with the following attributes (attributes without default are mandatory):
poetry2nix.mkPoetryEnv {
projectDir = ./.;
overrides = poetry2nix.overrides.withDefaults (self: super: { foo = null; });
}
See ./tests/override-support/default.nix for a working example.
Returns a list containing just the specified overlay, ignoring defaultPoetryOverrides
.
poetry2nix.mkPoetryEnv {
projectDir = ./.;
overrides = poetry2nix.overrides.withoutDefaults (self: super: { foo = null; });
}
Provides a source filtering mechanism that:
poetry2nix.cleanPythonSources {
src = ./.;
}
Sometimes when it can be convenient to create a custom instance of poetry2nix
with a different set of default overrides.
let
# self & super refers to poetry2nix
p2nix = poetry2nix.overrideScope' (self: super: {
# pyself & pysuper refers to python packages
defaultPoetryOverrides = super.defaultPoetryOverrides.extend (pyself: pysuper: {
my-custom-pkg = super.my-custom-pkg.overridePythonAttrs (oldAttrs: { });
});
});
in
p2nix.mkPoetryApplication {
projectDir = ./.;
}
or as a nixpkgs overlay:
let
pkgs = import <nixpkgs> {
overlays = [
# self & super refers to nixpkgs
(self: super: {
# p2self & p2super refers to poetry2nix
poetry2nix = super.poetry2nix.overrideScope' (p2nixself: p2nixsuper: {
# pyself & pysuper refers to python packages
defaultPoetryOverrides = p2nixsuper.defaultPoetryOverrides.extend (pyself: pysuper: {
my-custom-pkg = super.my-custom-pkg.overridePythonAttrs (oldAttrs: { });
});
});
})
];
};
in pkgs.poetry2nix.mkPoetryApplication {
projectDir = ./.;
}
Q. I'm experiencing one of the following errors, what do I do?
A. Have a look at the following document edgecase.md
For the experimental flakes functionality we provide poetry2nix as a flake providing an overlay to use with nixpkgs. Additionally, the flake provides a flake template to quickly start using poetry2nix in a project:
nix flake init --template github:nix-community/poetry2nix
Contributions to this project are welcome in the form of GitHub PRs. Please consider the following before creating PRs:
nix-shell --run "nixpkgs-fmt ."
to format everything.nix-build --keep-going --show-trace tests/default.nix
We have a Matrix room at #poetry2nix:blad.is.
Development of poetry2nix
has been supported by Tweag.
poetry2nix is released under the terms of the MIT license.