228 words, 2 min read

I'm using uv to manage the dependencies in our Python project.

When defining dependencies in the pyproject.toml file, for some dependencies, we add extras such as the fact that we want a binary version:

[project]
name = "docai"
version = "0.1.0"
description = "DocAI CLI"
requires-python = ">=3.11"
dependencies = [
    "fastapi[standard]==0.115.5",
    "psycopg[binary]==3.2.6",
]

We use uv compile to also export the list of dependencies to a requirements.txt file.

To do so, we execute:

uv pip compile --no-annotate --no-emit-options --extra dev --no-deps -o requirements.txt pyproject.toml

This however has the annoying side effect that it strips the extras:

# This file was autogenerated by uv via the following command:
#    uv pip compile --no-annotate --no-emit-options --extra dev --no-deps -o requirements.txt pyproject.toml
fastapi==0.115.5
psycopg==3.2.6

Turns out there is a way to keep these extras by using the option --no-strip-extras:

# This file was autogenerated by uv via the following command:
#    uv pip compile --no-annotate --no-emit-options --extra dev --no-deps --no-strip-extras -o requirements.txt pyproject.toml
fastapi[standard]==0.115.5
psycopg[binary]==3.2.6

It's a bit hidden in the documentation though:

By default, uv strips extras when outputting the compiled requirements. In other words, uv defaults to --strip-extras, while pip-compile defaults to --no-strip-extras. pip-compile is scheduled to change this default in the next major release (v8.0.0), at which point both tools will default to --strip-extras. To retain extras with uv, pass the --no-strip-extras flag to uv pip compile.