Nitropy installation failed

Hi,
the try to install pynitrokey on Fedora 41 failed:

sudo dnf install python pipx && pipx ensurepath && pipx install pynitrokey
Otherwise pipx is ready to go! :sparkles: :star2: :sparkles:
Fatal error from pip prevented installation. Full pip output in file:
/home/kgenz/.local/state/pipx/log/cmd_2025-02-25_12.17.08_1_pip_errors.log

pip failed to build package:
hidapi

Some possibly relevant errors from pip install:
error: subprocess-exited-with-error
/tmp/pip-install-0kthmmhg/hidapi_cb6df6b1074744909c4db3b4ce2da28f/hidapi/linux/hid.c:43:10: fatal error: libudev.h: No such file or directory
error: command β€˜/usr/bin/gcc’ failed with exit code 1
ERROR: Failed to build installable wheels for some pyproject.toml based projects (hidapi)

Error installing pynitrokey.

The logs show:

PIP STDOUT

Collecting pynitrokey
Using cached pynitrokey-0.7.3-py3-none-any.whl.metadata (4.5 kB)
Collecting cffi (from pynitrokey)
Using cached cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (1.5 kB)
Collecting click<9,>=8.1.6 (from pynitrokey)
Using cached click-8.1.8-py3-none-any.whl.metadata (2.3 kB)
Collecting cryptography<45,>=43 (from pynitrokey)
Downloading cryptography-44.0.1-cp39-abi3-manylinux_2_34_x86_64.whl.metadata (5.7 kB)
Collecting ecdsa (from pynitrokey)
Using cached ecdsa-0.19.0-py2.py3-none-any.whl.metadata (29 kB)
Collecting fido2<2,>=1.2.0 (from pynitrokey)
Using cached fido2-1.2.0-py3-none-any.whl.metadata (1.4 kB)
Collecting hidapi<0.14.0.post4,>=0.14.0.post1 (from pynitrokey)
Using cached hidapi-0.14.0.post2.tar.gz (172 kB)
Installing build dependencies: started
Installing build dependencies: finished with status β€˜done’
Getting requirements to build wheel: started
Getting requirements to build wheel: finished with status β€˜done’
Preparing metadata (pyproject.toml): started
Preparing metadata (pyproject.toml): finished with status β€˜done’
Collecting intelhex (from pynitrokey)
Using cached intelhex-2.3.0-py2.py3-none-any.whl.metadata (2.7 kB)
Collecting nkdfu (from pynitrokey)
Using cached nkdfu-0.2-py3-none-any.whl.metadata (1.4 kB)
Collecting nitrokey~=0.2.1 (from pynitrokey)
Using cached nitrokey-0.2.4-py3-none-any.whl.metadata (5.0 kB)
Collecting pyusb (from pynitrokey)
Using cached pyusb-1.3.1-py3-none-any.whl.metadata (2.5 kB)
Collecting requests (from pynitrokey)
Using cached requests-2.32.3-py3-none-any.whl.metadata (4.6 kB)
Collecting tqdm (from pynitrokey)
Using cached tqdm-4.67.1-py3-none-any.whl.metadata (57 kB)
Collecting tlv8 (from pynitrokey)
Using cached tlv8-0.10.0-py3-none-any.whl
Collecting click-aliases<2,>=1.0.5 (from pynitrokey)
Using cached click_aliases-1.0.5-py3-none-any.whl.metadata (1.7 kB)
Collecting semver (from pynitrokey)
Using cached semver-3.0.4-py3-none-any.whl.metadata (6.8 kB)
Collecting nethsm<2,>=1.2.1 (from pynitrokey)
Using cached nethsm-1.2.1-py3-none-any.whl.metadata (5.8 kB)
Collecting pycparser (from cffi->pynitrokey)
Using cached pycparser-2.22-py3-none-any.whl.metadata (943 bytes)
Collecting setuptools>=19.0 (from hidapi<0.14.0.post4,>=0.14.0.post1->pynitrokey)
Using cached setuptools-75.8.0-py3-none-any.whl.metadata (6.7 kB)
Collecting certifi (from nethsm<2,>=1.2.1->pynitrokey)
Using cached certifi-2025.1.31-py3-none-any.whl.metadata (2.5 kB)
Collecting python-dateutil (from nethsm<2,>=1.2.1->pynitrokey)
Using cached python_dateutil-2.9.0.post0-py2.py3-none-any.whl.metadata (8.4 kB)
Collecting typing_extensions~=4.3.0 (from nethsm<2,>=1.2.1->pynitrokey)
Using cached typing_extensions-4.3.0-py3-none-any.whl.metadata (6.3 kB)
Collecting urllib3<2.1,>=2.0 (from nethsm<2,>=1.2.1->pynitrokey)
Using cached urllib3-2.0.7-py3-none-any.whl.metadata (6.6 kB)
Collecting crcmod<2.0,>=1.7 (from nitrokey~=0.2.1->pynitrokey)
Using cached crcmod-1.7-py3-none-any.whl
Collecting protobuf<6.0,>=5.26 (from nitrokey~=0.2.1->pynitrokey)
Using cached protobuf-5.29.3-cp38-abi3-manylinux2014_x86_64.whl.metadata (592 bytes)
Collecting pyserial<4.0,>=3.5 (from nitrokey~=0.2.1->pynitrokey)
Using cached pyserial-3.5-py2.py3-none-any.whl.metadata (1.6 kB)
Collecting charset-normalizer<4,>=2 (from requests->pynitrokey)
Using cached charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (35 kB)
Collecting idna<4,>=2.5 (from requests->pynitrokey)
Using cached idna-3.10-py3-none-any.whl.metadata (10 kB)
Collecting six>=1.9.0 (from ecdsa->pynitrokey)
Using cached six-1.17.0-py2.py3-none-any.whl.metadata (1.7 kB)
Collecting fire (from nkdfu->pynitrokey)
Using cached fire-0.7.0-py3-none-any.whl
Collecting libusb1>=1.9.3 (from nkdfu->pynitrokey)
Using cached libusb1-3.2.0-py3-none-any.whl.metadata (15 kB)
Collecting termcolor (from fire->nkdfu->pynitrokey)
Using cached termcolor-2.5.0-py3-none-any.whl.metadata (6.1 kB)
Using cached pynitrokey-0.7.3-py3-none-any.whl (159 kB)
Using cached click-8.1.8-py3-none-any.whl (98 kB)
Using cached click_aliases-1.0.5-py3-none-any.whl (3.5 kB)
Downloading cryptography-44.0.1-cp39-abi3-manylinux_2_34_x86_64.whl (4.2 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.2/4.2 MB 6.5 MB/s eta 0:00:00
Using cached cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (479 kB)
Using cached fido2-1.2.0-py3-none-any.whl (219 kB)
Using cached nethsm-1.2.1-py3-none-any.whl (709 kB)
Using cached nitrokey-0.2.4-py3-none-any.whl (161 kB)
Using cached requests-2.32.3-py3-none-any.whl (64 kB)
Using cached semver-3.0.4-py3-none-any.whl (17 kB)
Using cached ecdsa-0.19.0-py2.py3-none-any.whl (149 kB)
Using cached intelhex-2.3.0-py2.py3-none-any.whl (50 kB)
Using cached nkdfu-0.2-py3-none-any.whl (16 kB)
Using cached pyusb-1.3.1-py3-none-any.whl (58 kB)
Using cached tqdm-4.67.1-py3-none-any.whl (78 kB)
Using cached certifi-2025.1.31-py3-none-any.whl (166 kB)
Using cached charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (144 kB)
Using cached idna-3.10-py3-none-any.whl (70 kB)
Using cached libusb1-3.2.0-py3-none-any.whl (65 kB)
Using cached protobuf-5.29.3-cp38-abi3-manylinux2014_x86_64.whl (319 kB)
Using cached pyserial-3.5-py2.py3-none-any.whl (90 kB)
Using cached setuptools-75.8.0-py3-none-any.whl (1.2 MB)
Using cached six-1.17.0-py2.py3-none-any.whl (11 kB)
Using cached typing_extensions-4.3.0-py3-none-any.whl (25 kB)
Using cached urllib3-2.0.7-py3-none-any.whl (124 kB)
Using cached pycparser-2.22-py3-none-any.whl (117 kB)
Using cached python_dateutil-2.9.0.post0-py2.py3-none-any.whl (229 kB)
Using cached termcolor-2.5.0-py3-none-any.whl (7.8 kB)
Building wheels for collected packages: hidapi
Building wheel for hidapi (pyproject.toml): started
Building wheel for hidapi (pyproject.toml): finished with status β€˜error’
Failed to build hidapi

PIP STDERR

error: subprocess-exited-with-error

Γ— Building wheel for hidapi (pyproject.toml) did not run successfully.
β”‚ exit code: 1
╰─> [11 lines of output]
running bdist_wheel
running build
running build_ext
building β€˜hid’ extension
creating build/temp.linux-x86_64-cpython-313/tmp/pip-install-0kthmmhg/hidapi_cb6df6b1074744909c4db3b4ce2da28f/hidapi/linux
gcc -fno-strict-overflow -Wsign-compare -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -fcf-protection -fexceptions -fcf-protection -fexceptions -fcf-protection -fexceptions -O3 -fPIC -I/tmp/pip-install-0kthmmhg/hidapi_cb6df6b1074744909c4db3b4ce2da28f/hidapi/hidapi -I/home/kgenz/.local/share/pipx/venvs/pynitrokey/include -I/usr/include/python3.13 -c /tmp/pip-install-0kthmmhg/hidapi_cb6df6b1074744909c4db3b4ce2da28f/hidapi/linux/hid.c -o build/temp.linux-x86_64-cpython-313/tmp/pip-install-0kthmmhg/hidapi_cb6df6b1074744909c4db3b4ce2da28f/hidapi/linux/hid.o
/tmp/pip-install-0kthmmhg/hidapi_cb6df6b1074744909c4db3b4ce2da28f/hidapi/linux/hid.c:43:10: fatal error: libudev.h: No such file or directory
43 | #include <libudev.h>
| ^~~~~~~~~~~
compilation terminated.
error: command β€˜/usr/bin/gcc’ failed with exit code 1
[end of output]

note: This error originates from a subprocess, and is likely not a problem with pip.
ERROR: Failed building wheel for hidapi
ERROR: Failed to build installable wheels for some pyproject.toml based projects (hidapi)

Any Idea, what is wrong here and how to solve it?

Kind regards,
Kay-Uwe

does

dnf install libudev-devel

work?

Unfortunately, no it didn’t.

pip failed to build package:
hidapi

Some possibly relevant errors from pip install:
error: subprocess-exited-with-error
hidraw.c:36:10: fatal error: Python.h: No such file or directory
error: command β€˜/usr/bin/gcc’ failed with exit code 1
ERROR: Failed to build installable wheels for some pyproject.toml based projects (hidapi)

… that one was easy to solve:

sudo dnf install python3-devel

So on a default Fedora 41 it seems, you need:

sudo dnf install libudev-devel python3-devel python pipx && pipx ensurepath && pipx install pynitrokey

Python isn’t a very good language for writing software you want to distribute, so in the long run it would be better to have the client software written in a compiled language that can produce statically linked binaries. Preferably something not C/C++, but rather Rust or Go since those have sensible build toochains.

(I think the closest existing alternative may be a (third party) Rust CLI. I have also been writing a CLI in Go for a project, but that only supports the NetHSM and isn’t complete. If people were interested in collaborating on a Go CLI I can probably publish it)