Uv2nix - Build & develop Python projects using uv with Nix

Uv is an exciting new Python package & project manager that’s been rapidly gaining popularity thanks to it’s speed and ease of use.

Uv2nix

Shortly after uv announced lock file support I got hacking on uv2nix.
I just took the experimental label off which means that I’m fairly confident that APIs not explicitly marked unstable won’t change, but will keep evolving together with uv.

uv & uv2nix together can be seen as a next generation of tools replacing Poetry & poetry2nix (I’m the author of poetry2nix).

Key Features

  • Pure Nix, no import-from-derivation
  • Package level granular builds, one Nix package per Python package
  • Support for editable packages with pure eval
  • Support for cyclic dependencies
  • Cross compilation

Head over to the docs for an introduction!

49 Likes

Wow, @adisbladis. I imagine it would provide a well needed alleviation to the struggles of many a Nixer. Thank you!

2 Likes

This was literally perfect timing, as I am just about to migrate my PhD monorepo to UV. The inner workings you showed me at NixCon really impressed me! Thank you so much. :smile:

1 Like

I started playing with this in November when I saw poetry2nix was deprecated. I needed to get an mkdocs site up and it was fairly straightforward. Awesome work!

1 Like

Great addition! I would just recommend to simplify the hello-world example. Compared to this simple pyproject.nix the Uv flake looks way too daunting. I realize that most of it is comments and optional config, but that’s the point that: they belong to a reference, not a quickstart.

2 Likes

Wow great! I packaged migrate-to-uv for nix to make migration more easy. Looking forward to work more with uv.

2 Likes

I ended up needing to make a file for a couple Python projects in the same repo where I just hid all that behind a small callPackage interface for the readability of my flake. I wonder if there could be some handy functions to return projects and dev shells, including the impure one that’s useful for initializing a uv project.

Overall, it currently feels like a little more boilerplate than I was expecting (good luck explaining it to my coworkers), though otherwise works great.

I don’t see the usage example as a quickstart, but as an introduction to uv2nix and it’s concepts. I don’t want a quickstart as I don’t believe it results in empowered users.

These two examples are massively different complexity wise.
The pyproject.nix example is a translation of pyproject.toml to nixpkgs buildPythonPackage, but uv2nix requires way more explanation.

This may seem daunting to you now, but I’m hoping that being verbose up front will result in a better understanding.

The API is designed with a few things in mind, but the two most important to consider here are flexibility and performance.

Flexibility wise you need access to the overlay composition, platform quirks & so on.
Making higher level wrappers would be too much sacrifice here.

The API is designed to front load as much as possible, which is why things like project loaders happen in in the toplevel flake scope with no package sets attached to them.
For example things like the PEP-508 marker parser are implemented in pure Nix and relatively slow, we really want to avoid re-parsing.

If you wrap this up in a function that also takes the package set you end up re-evaluating a lot.

A possible way to reduce boilerplate within the same repo is to use uv workspaces.

3 Likes