The three C extensions (_input, _uinput, _ecodes) have no shared mutable global state, so there are no data races to fix. Supporting free-threaded Python (3.13+ nogil) is essentially a no-op correctness-wise — just add PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED) to the PyInit_ function of each extension (including the ecodes.c generator). Without this, importing evdev in a free-threaded build silently re-enables the GIL for the whole interpreter.
As a follow-up, wrapping blocking read()/ioctl() calls in Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS would allow true parallelism across threads reading different devices.
Happy to open a PR if there's interest.
The three C extensions (
_input,_uinput,_ecodes) have no shared mutable global state, so there are no data races to fix. Supporting free-threaded Python (3.13+ nogil) is essentially a no-op correctness-wise — just addPyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED)to thePyInit_function of each extension (including theecodes.cgenerator). Without this, importing evdev in a free-threaded build silently re-enables the GIL for the whole interpreter.As a follow-up, wrapping blocking
read()/ioctl()calls inPy_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADSwould allow true parallelism across threads reading different devices.Happy to open a PR if there's interest.