Creating a python derivation is not trivial. python has already lots of issue with version conflict. So if you need to create one pythonnix derivation, you just hope it does not have dependency.
Otherwise, there is some mitigation, but it’s not easy to deal it.
The easiest one I find is to manually pip install in the shellHook. It does not quite respect nix reproducible philosophy however:
{ # ... devShells.default = pkgs.mkShell { packages = with pkgs; [ python3 python3Packages.pip python3Packages.virtualenv ]; shellHook = '' if [ ! -d .venv ]; then virtualenv .venv fi # Activate the virtual environment source .venv/bin/activate pip install presenterm-export ''; };}
Context
I wanted to install [presenterm-export][] to my local computer, so I could export my markdown slides. Unfortunately, this tool is not present yet in nixpkgs.
I’m using direnv to automatically install the tools when I go to a folder. So I created a flake.nix with the following content:
Still, I managed to do something. I created a presenter-export.nix with the following:
{ # Builtin nix function that also calls mkDerivation. buildPythonPackage, # Fetch the tarball from pypi. fetchPypi, setuptools, # Pypi dependencies to install. # Found from code source: https://github.com/mfontanini/presenterm-export/blob/454ca9e73adb38f57ba93f4e4ed51695d04432df/pyproject.toml#L17-L20. ansi2html, dataclass-wizard, libtmux, weasyprint,}: buildPythonPackage rec { pname = "presenterm-export"; version = "0.2.3"; pyproject = true; src = fetchPypi { # For some reason, the name in pypi is using a underscore... pname = "presenterm_export"; inherit version; hash = "sha256-cevPqvW3vX6gAa7+MElIZYbMaJHoP8juC2o/6eci13Y="; }; build-system = [ setuptools ]; dependencies = [ ansi2html libtmux weasyprint dataclass-wizard ];}
$ nix developerror: builder for '/nix/store/q0i5nk2zmmy4kzawknbhk3qqbymccb06-python3.11-presenterm-export-0.2.3.drv' failed with exit code 1; last 10 log lines: > removing build/bdist.linux-x86_64/wheel > Successfully built presenterm_export-0.2.3-py3-none-any.whl > Finished creating a wheel... > Finished executing pypaBuildPhase > Running phase: pythonRuntimeDepsCheckHook > Executing pythonRuntimeDepsCheck > Checking runtime dependencies for presenterm_export-0.2.3-py3-none-any.whl > - ansi2html==1.8.0 not satisfied by version 1.9.2 > - libtmux==0.23.2 not satisfied by version 0.37.0 > - weasyprint==62.3.0 not satisfied by version 61.2 For full logs, run 'nix log /nix/store/q0i5nk2zmmy4kzawknbhk3qqbymccb06-python3.11-presenterm-export-0.2.3.drv'.
It did not work (I hope it would 😔)…
It seems I need to have the specific version of the dependencies.
❌ Find the nixpkgs SHA to download the specific version of a dependency
We can use Nix Package Versions to find the right nix version / HASH to get the specific version of a dependency.
I could find the SHA for ansi2html. However, for some reasons, I could not find anything for libtmux and weasyprint.
at /nix/store/avci5b2qjsxkcc17fpl1gralpv6b4xsd-source/pkgs/stdenv/generic/make-derivation.nix:376:7:
375| depsBuildBuild = elemAt (elemAt dependencies 0) 0;
376| nativeBuildInputs = elemAt (elemAt dependencies 0) 1;
| ^
377| depsBuildTarget = elemAt (elemAt dependencies 0) 2;
(stack trace truncated; use '--show-trace' to show the full trace)
error: Python version mismatch in 'python3.12-presenterm-export-0.2.3':
The Python derivation 'python3.12-presenterm-export-0.2.3' depends on a Python derivation
named 'python3.11-ansi2html-1.8.0', but the two derivations use different versions
of Python:
'python3.12-presenterm-export-0.2.3' uses /nix/store/z7xxy35k7620hs6fn6la5fg2lgklv72l-python3-3.12.4
'python3.11-ansi2html-1.8.0' uses /nix/store/sxr2igfkwhxbagri49b8krmcqz168sim-python3-3.11.8
Possible solutions:
* If 'python3.11-ansi2html-1.8.0' is a Python library, change the reference to 'python3.11-ansi2html-1.8.0'
in the propagatedBuildInputs of 'python3.12-presenterm-export-0.2.3' to use a 'python3.11-ansi2html-1.8.0' built from the same
version of Python
* If 'python3.11-ansi2html-1.8.0' is used as a tool during the build, move the reference to
'python3.11-ansi2html-1.8.0' in 'python3.12-presenterm-export-0.2.3' from propagatedBuildInputs to nativeBuildInputs
* If 'python3.11-ansi2html-1.8.0' provides executables that are called at run time, pass its
bin path to makeWrapperArgs:
makeWrapperArgs = [ "--prefix PATH : ${lib.makeBinPath [ ansi2html ] }" ];
at /nix/store/356lp2h4rvgkvlw83pnf092p3f858ph8-source/presenterm-export.nix:14:3
Fail
Not possible to fetch different versions of the dependencies because they would use a different python version, hence a conflict. Not sure if it’s possible or not to use the same python.
❌ dependencies as nativeBuildInputs
I tried to use their one of their option in presenter-export.nix:
However, that did not went well. It downloaded 7GB of data to finally failed with the following error:
error: builder for '/nix/store/rn12q26sw4yxj297q17gwf5g0fdwm61n-audit-3.1.2.drv' failed with exit code 1;
last 10 log lines:
> checking for python version... 3.12
> checking for python platform... linux
> checking for GNU default python prefix... ${prefix}
> checking for GNU default python exec_prefix... ${exec_prefix}
> checking for python script directory (pythondir)... ${PYTHON_PREFIX}/lib/python3.12/site-packages
> checking for python extension module directory (pyexecdir)... ${PYTHON_EXEC_PREFIX}/lib/python3.12/site-packages
> Traceback (most recent call last):
> File "<string>", line 1, in <module>
> ModuleNotFoundError: No module named 'distutils'
> configure: error: Python explicitly requested and python headers were not found
For full logs, run 'nix log /nix/store/rn12q26sw4yxj297q17gwf5g0fdwm61n-audit-3.1.2.drv'.
error: 1 dependencies of derivation '/nix/store/64a12rhqh517x7pdpgy039a0byhql01k-dbus-1.14.10.drv' failed to build
error: 1 dependencies of derivation '/nix/store/vn2bjd4p48d85k4nggb5gddbazjvnrrv-linux-pam-1.6.1.drv' failed to build
error: 1 dependencies of derivation '/nix/store/cjfq86dl1pl6bbxdbmnbg8vzljx2xh6s-cups-2.4.8.drv' failed to build
error: 1 dependencies of derivation '/nix/store/762b7ph538mbgy71wa7dnhr2k4wdxqzh-util-linux-minimal-2.39.4.drv' failed to build
error: 1 dependencies of derivation '/nix/store/wfb10mpxsiskh8jyb179nm57v286g0ca-e2fsprogs-1.47.1.drv' failed to build
error: 1 dependencies of derivation '/nix/store/fap3yi9x0zndgabcyc3mxamp5l2vk133-ghostscript-with-X-10.03.1.drv' failed to build
error: 1 dependencies of derivation '/nix/store/1dkc10jn0y4d0v8gsz5ay0kmhwykzbfc-glib-2.80.3.drv' failed to build
error: 1 dependencies of derivation '/nix/store/41zm6zhiplh8zrnmdakgsfzlicpdqpl8-libarchive-3.7.4.drv' failed to build
error: 1 dependencies of derivation '/nix/store/law0hvlp64scrxmhz6hmscmblz4f5zz6-python3.12-weasyprint-62.2.drv' failed to build
error: 1 dependencies of derivation '/nix/store/mjajks3frz923gfnp9923afv4l346my9-cmake-3.29.6.drv' failed to build
error: 1 dependencies of derivation '/nix/store/rvhjakhyk9xjj14b25xq86rpsm160vdb-python3.12-presenterm-export-0.2.3.drv' failed to build
error: 1 dependencies of derivation '/nix/store/nx8i4d1yqzvsr89iswvfwinj958x41f7-nix-shell-env.drv' failed to build
Fail
Could not make it work when the dependencies were packaged with a different version of python…
We could also use shellHook so we don’t have to manually perform those steps:
{ # ... devShells.default = pkgs.mkShell { packages = with pkgs; [ # ... ]; shellHook = '' # Create a virtual environment in the .venv directory if [ ! -d .venv ]; then virtualenv .venv fi # Activate the virtual environment source .venv/bin/activate if [ ! type presenterm-export >/dev/null 2>&1 ]; then pip install presenterm-export fi echo "Virtual environment activated. Use 'deactivate' to exit." ''; }; });}
The installation went well with the python virtualenv. However, the execution, not so well:
$ # Perform export$ presenterm --export-pdf SLIDES.mdtmux version: 3.4Writing temporary files into /tmp/tmp7bl8s1ncRunning presentation to capture slide...Running '/nix/store/27s9ibvam9qcyv120jaijw43j2hani0c-presenterm-0.7.0/bin/presenterm' '--export' '/home/l-lin/work/welcoming-kubernetes/SLIDES.md''presenterm-export' execution failed:Traceback (most recent call last): File "/home/l-lin/work/welcoming-kubernetes/.venv/bin/presenterm-export", line 8, in <module> sys.exit(main()) ^^^^^^ File "/home/l-lin/work/welcoming-kubernetes/.venv/lib/python3.12/site-packages/presenterm_export/cli.py", line 112, in main run(args, metadata) File "/home/l-lin/work/welcoming-kubernetes/.venv/lib/python3.12/site-packages/presenterm_export/cli.py", line 49, in run presentation = capture_slides(args.rest, metadata.commands) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/l-lin/work/welcoming-kubernetes/.venv/lib/python3.12/site-packages/presenterm_export/capture.py", line 31, in capture_slides
shellHook = '' # ... if [ ! type weasyprint >/dev/null 2>&1 ]; then pip install weasyprint fi # ...'';
weasyprint is indeed installed, but there are errors:
$ weasyprint --info-----WeasyPrint could not import some external libraries. Please carefully follow the installation steps before reporting an issue:https://doc.courtbouillon.org/weasyprint/stable/first_steps.html#installationhttps://doc.courtbouillon.org/weasyprint/stable/first_steps.html#troubleshooting-----Traceback (most recent call last): File "/home/l-lin/work/welcoming-kubernetes/.venv/bin/weasyprint", line 5, in <module> from weasyprint.__main__ import main File "/home/l-lin/work/welcoming-kubernetes/.venv/lib/python3.12/site-packages/weasyprint/__init__.py", line 419, in <module> from .css import preprocess_stylesheet # noqa: I001, E402 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/l-lin/work/welcoming-kubernetes/.venv/lib/python3.12/site-packages/weasyprint/css/__init__.py", line 28, in <module> from .computed_values import COMPUTER_FUNCTIONS File "/home/l-lin/work/welcoming-kubernetes/.venv/lib/python3.12/site-packages/weasyprint/css/computed_values.py", line 9, in <module> from ..text.ffi import ffi, pango, units_to_double File "/home/l-lin/work/welcoming-kubernetes/.venv/lib/python3.12/site-packages/weasyprint/text/ffi.py", line 431, in <module> gobject = _dlopen( ^^^^^^^^ File "/home/l-lin/work/welcoming-kubernetes/.venv/lib/python3.12/site-packages/weasyprint/text/ffi.py", line 420, in _dlopen return ffi.dlopen(names[0]) # pragma: no cover ^^^^^^^^^^^^^^^^^^^^ File "/home/l-lin/work/welcoming-kubernetes/.venv/lib/python3.12/site-packages/cffi/api.py", line 150, in dlopen lib, function_cache = _make_ffi_library(self, name, flags) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/l-lin/work/welcoming-kubernetes/.venv/lib/python3.12/site-packages/cffi/api.py", line 832, in _make_ffi_library backendlib = _load_backend_lib(backend, libname, flags) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/l-lin/work/welcoming-kubernetes/.venv/lib/python3.12/site-packages/cffi/api.py", line 827, in _load_backend_lib raise OSError(msg)OSError: cannot load library 'gobject-2.0-0': gobject-2.0-0: cannot open shared object file: No such file or directory. Additionally, ctypes.util.find_library() did not manage to locate a library called 'gobject-2.0-0'
It seems there are dependencies that needs to be installed.
However, I still got the error when trying to export my slides in PDF:
$ presenterm --export-pdf SLIDES.mdtmux version: 3.4Writing temporary files into /tmp/tmp2jpe7q9iRunning presentation to capture slide...Running '/nix/store/27s9ibvam9qcyv120jaijw43j2hani0c-presenterm-0.7.0/bin/presenterm' '--export' '/home/l-lin/work/welcoming-kubernetes/SLIDES.md''presenterm-export' execution failed:Traceback (most recent call last): File "/home/l-lin/work/welcoming-kubernetes/.venv/bin/presenterm-export", line 8, in <module> sys.exit(main()) ^^^^^^ File "/home/l-lin/work/welcoming-kubernetes/.venv/lib/python3.12/site-packages/presenterm_export/cli.py", line 112, in main run(args, metadata) File "/home/l-lin/work/welcoming-kubernetes/.venv/lib/python3.12/site-packages/presenterm_export/cli.py", line 49, in run presentation = capture_slides(args.rest, metadata.commands) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/l-lin/work/welcoming-kubernetes/.venv/lib/python3.12/site-packages/presenterm_export/capture.py", line 31, in capture_slides