Packaging python bindings so they can be used as a dependency

I’d like to ask what is the proper way to package an applications with python bindings (which may be built into an .so lib). Because just using toPythonModule is not enough at all for setuptools of other packages to see it…
I mean if you use such package as a dependency in another package you get the bindings to the PYTHONPATH and such BUT setup.cfg/ will fail with not seeing the dependency!

I have a workaround which is not using toPythonModule at all. Example:

{ python, ocp-library, writeText }:

python.pkgs.buildPythonPackage {
  pname = "OCP";
  version = "0.0.0";
  src = ocp-library;
  format = "pyproject";

  prePatch =
      pyproject = writeText "pyproject.toml" ''
        requires = [
        build-backend = "setuptools.build_meta"

      setup_cfg = writeText "setup.cfg" ''
        name = OCP

        packages = .

        * = *.so
      cp "${pyproject}" ./pyproject.toml;
      cp "${setup_cfg}" ./setup.cfg
      ls -la

  pythonImportsCheck = [ "OCP" "" ];

where the ocp-library in this example is a package which is generating some python bindings.

BUT it really feels like a dirty hack because

  • What is the toPythonModule good for then?
  • I haven’t seen anybody using such construct.

An example of a naive approch which does not work:

{ toPythonModule, stdenv, fetchFromGitHub, cmake, numpy, swig }:

toPythonModule (stdenv.mkDerivation rec {
  pname = "nlopt";
  version = "2.7.0";

  src = fetchFromGitHub {
    owner = "stevengj";
    repo = pname;
    rev = "v${version}";
    sha256 = "sha256-+wSQ5H5I4xbwArdFjUkFdc1+HX7IcmRXf1vc8ljyqHY=";

  buildInputs = [

  cmakeFlags = [

if you use such package as a dependency in another python package you get an error such as this:

python3.9-cadquery> Finished executing setuptoolsBuildPhase
python3.9-cadquery> installing
python3.9-cadquery> Executing pipInstallPhase
python3.9-cadquery> /build/source/dist /build/source
python3.9-cadquery> Processing ./cadquery-2.2.dev454+g3032e0f.d19800102-py3-none-any.whl
python3.9-cadquery> Requirement already satisfied: multimethod in /nix/store/n5slcih424x21055h7ws3m9m7apqrq0j-python3.9-multimethod-1.6/lib/python3.9/site-packages (from cadquery==2.2.dev454+g3032e0f.d19800102) (1.6)
python3.9-cadquery> Requirement already satisfied: typish in /nix/store/jsjwg8ml8d20w7682mfgxaj4gngddx0z-python3.9-typish-1.9.3/lib/python3.9/site-packages (from cadquery==2.2.dev454+g3032e0f.d19800102) (1.9.3)
python3.9-cadquery> Requirement already satisfied: ezdxf in /nix/store/w1w1xl98gqc0kzwx4rm8mkis69pnkrd7-python3.9-ezdxf-0.17.1/lib/python3.9/site-packages (from cadquery==2.2.dev454+g3032e0f.d19800102) (0.17.1)
python3.9-cadquery> ERROR: Could not find a version that satisfies the requirement nlopt (from cadquery) (from versions: none)
python3.9-cadquery> ERROR: No matching distribution found for nlopt

I can apply my superdooper hack. But I want to learn some more proper way to do this. Any help would be appreciated.

You are going to need a dist info folder. Nowadays these are created when creating a Python wheel but it is also possible build systems create one themselves without creating a wheel.

The function is just providing meta for the nix tooling to work. It doesn’t impact the build.