Python Glib introspection fails


Since my recent system upgrade to 24.05, I slowly grind through each things that broke after the upgrade.

Today I try to fix a python script that is called from waybar to tell the currently playing music. It has not been made by me and worked as intended after the upgrade but do not start anymore.

When launching, I get the following error: ImportError: cannot import name GLib, introspection typelib not found

It seems to come from an from gi import Glib import in the script. When running the same import from an interpreter, I get the same error.

After some search about this error, if found it could be a missing package, like pygobject3 or gobject-introspection, however I have added theses to my default python installation, and it does not change anything.

Here is a snippet of what is in my config:

  pyPkgs = ps: with ps; [
  # [...]
  home.packages = with pkgs; [
    # [...]
    # Python
    (pkgs.python311.withPackages pyPkgs)

I have a feeling about what is the Glib introspection, but actually no idea of how it works technically with python. Has something changed in 24.05 that could have broke that ?

You’d have to actually package the python script; simply putting dependencies in home.packages won’t help here.

glib typelib is now in glib not in gobject-introspection (this was a upstream change). I did some fixes in {libratbag,openrazer-daemon,whipper}: fix typelib error by Artturin · Pull Request #316717 · NixOS/nixpkgs · GitHub

glib typelib is now in glib not in gobject-introspection (this was a upstream change)

I actually read that PR before and tried in a nix shell with glib installed. No more success…

You’d have to actually package the python script; simply putting dependencies in home.packages won’t help here

I was afraid of this answer… Python things cant’t be easy with nixos. I guess it’s time for me to learn packaging things, all my previous attemps were failed.

You need a shell with both glib and gobject-introspection – the latter contains a setup hook that sets the required environment variable.

I just tried, with no more success…
I will try to package the script.

Things start to get weird.
I have been able to successfully start the script in a nix-shell with the following shell.nix:

with import <nixpkgs> {};
with pkgs.python3Packages;

buildPythonPackage rec {
  name = "mypackage";
  src = ./;
  propagatedBuildInputs = [ glib gobject-introspection dbus-python pygobject3 ];

However, it won’t launch in a nix shell nixpkgs#glib nixpkgs#gobject-introspection nixpkgs#python311 nixpkgs#python311Packages.dbus-python nixpkgs#python311Packages.pygobject3 (fails importing dbus)

And it neither launch when packaging and building the package with the following config:

{ lib, pkgs, python311Packages }:
with python311Packages;
buildPythonPackage {
  pname = "player-mpris";
  version = "1.0";

  propagatedBuildInputs = [ dbus-python pygobject3 pkgs.gobject-introspection pkgs.glib ];

  src = ./.;
#!/usr/bin/env python3

from setuptools import setup, find_packages

      # Modules to import from other scripts:
      # Executables

In this case it also fails with the introspection typelib not found error.

I don’t understand what is different between the shell.nix and the package.

Despite the similar name nix shell, is something completely different from nix-shell – unlike the older nix-shell command, it won’t run the setup hooks that set the environment variables. See e.g. Using `nix run` with several packages - #3 by jtojnar or Flakes: how to make `pkg-config` work with `nix shell`? - #2 by sternenseemann

mkDerivation and similar helpers like buildPythonPackage will run the setup hooks listed in inputs, which will make the environment variables available at build time but it is your responsibility to ensure they are available at runtime.

You can achieve that by using a wrapper.

Hmm, is there a documentation somewhere on how to use theses wrappers or do you know a package in nixpkgs that uses them that I could read ?
I feel a bit lost with what I saw on the Nixpkgs reference.

Ok, I got it to work. I just needed to add WrapGAppsNoGuiHook to my build inputs.

However I don’t understand what is going on here. How could a build dependency change the runtime behavior ?

As the name suggests, setup hooks hook into the generic builder of the stdenv and modify it.

wrapGAppsHook* family, specifically, replaces every executable in $out/bin and other similar directories with a program that sets some environment variables (as mentioned in the reference) and then executes the original program.

Okay I get it, this is why it works when adding Hooks to build inputs but not when adding them to home packages.
Thank’s for the help !

Yeah, generally, you should only ever install executable programs through environment.systemPackages/home.packages. See also FAQ: I installed a library but my compiler is not finding it. Why?