I'm working on a python application built with uv. The application is under active development, and I want to be able to tie its outputs to the version of the software (it generates a file containing results, and I want the version to be included in that output). I'm lazy, so I don't want to be manually updating the semantic version in the pyproject.toml, I just want to be able to do something like this:
> uv run myapp
Usage: myapp ...
Version: {the git hash with dirty indicator}
> uv venv
> source .venv/bin/activate
(myapp)> myapp --help
Usage: myapp ...
Version: {the git hash with dirty indicator}
In the past (with other compiled languages) I would generate a file at build time that gets packaged into the executable. Later at runtime I would read this file and print out the version. I've gotten something similar to work with uv if I use:
>python write_version_to_file.py
>uv pip install --force-reinstall . # uv run myapp would also work here
But this feels clunky because it is two steps, and requires the "force" flag for pip. I feel like it would be cleaner if I could hook into uv in a way that I can dynamically generate my version file right before uv run
or via a uv pip install
. Is there a good pattern to do this? Would there be a better way to do this without trying to tie into uv/hatch?
ps: I've tried versioningit, which looks very close to what I want, but it seems to specifically address the uv pip install
workflow, and not the uv run
workflow.
another thing I tried was to implement BuildHookInterface as a custom hatch hook
pyproject.toml:
[tool.hatch.build.hooks.custom]
path = "write_version_to_file.py"
class = "VersionBuildHook"
but this also only ran consistently with uv pip install
and not uv run
for reference, this is what the relevant parts of my pyproject.toml look like:
[project.scripts]
myapp = "mypkg.myapp:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build]
artifacts = ["src/mypkg/version.properties"]