How can I write a Python package derivation in a flake?

That should almost work, only you are mixing two different paradigms:

  • python packages are created using buildPythonPackage and take python dependencies in propagatedBuildInputs
  • projects that need Python with some extra Python modules need python.withPackages … in inputs

So I would replace

with either

        pkgs.python3Packages.buildPythonPackage rec {
          name = "getBook";
          src = ./.;
          propagatedBuildInputs = with python3Packages; [
            requests
            libgenApi
          ];
        };

or

        pkgs.stdenv.mkDerivation rec {
          name = "getBook";
          src = ./.;
          buildInputs = [
            (python3.withPackages (ps: with ps; [
              requests
              libgenApi
            ]))
          ];
        };

depending on whether getBook is one or the other. Possibly buildPythonApplication, if it is application and not a module.

2 Likes

It seems I still get the same error, with both of those variations. Here’s the one I’m using now:

{
  description = "Just some python scripts to download books.";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs?ref=nixpkgs-unstable";
    utils.url = "github:numtide/flake-utils";
  };
  outputs = { self, nixpkgs, utils }: {
    devShell = self.defaultPackage;
    defaultPackage.x86_64-linux =
      with import nixpkgs { system = "x86_64-linux"; };
      let
        libgenApi = pkgs.python3Packages.buildPythonPackage rec {
          pname = "libgen-api";
          version = "0.3.0";
          doCheck = false;
          propagatedBuildInputs = with pkgs.python3Packages; [
            setuptools
            wheel
	          beautifulsoup4
	        ];
          src = (pkgs.python3Packages.fetchPypi {
            inherit pname version;
            sha256 = "08fdd5ef7c96480ad11c12d472de21acd32359996f69a5259299b540feba4560";
        });};
      in
        pkgs.python3Packages.buildPythonPackage rec {
          name = "getBook";
          src = ./.;
          propagatedBuildInputs = with pkgs.python3Packages; [
            requests
            libgenApi
          ];
        };
  };
}

Do I need to declare the Pypi package as an input or something?

Looks like you are using wrong hash (of toolz package), so that gets used instead.

If you change the hash to sha256 = "";, you will get complain:

warning: found empty hash, assuming 'sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='
error: --- Error ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- nix
builder for '/nix/store/7j90gbgzcj6cq3c8b43rlfrq6vqz7614-libgen-api-0.3.0.tar.gz.drv' failed with exit code 1; last 10 log lines:
  curl: (22) The requested URL returned error: 404 
  
  trying https://pypi.io/packages/source/l/libgen-api/libgen-api-0.3.0.tar.gz
    % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                   Dload  Upload   Total   Spent    Left  Speed
  100   122  100   122    0     0   1119      0 --:--:-- --:--:-- --:--:--  1119
  100   280  100   280    0     0    853      0 --:--:-- --:--:-- --:--:--  1958
    0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  curl: (22) The requested URL returned error: 404 
  error: cannot download libgen-api-0.3.0.tar.gz from any mirror

That is because PyPI only has that package as wheel

Looking at

you need to pass it format = "wheel";.

I got it to work by using GitHub instead of PyPi, but now I’m getting another error:

{
  description = "Just some python scripts to download books.";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs?ref=nixpkgs-unstable";
    utils.url = "github:numtide/flake-utils";
  };
  outputs = { self, nixpkgs, utils }: {
    devShell = self.defaultPackage;
    defaultPackage.x86_64-linux =
      with import nixpkgs { system = "x86_64-linux"; };
      let
        libgenApi = pkgs.python3Packages.buildPythonPackage rec {
          pname = "libgen-api";
          version = "0.3.0";
          doCheck = false;
          propagatedBuildInputs = with pkgs.python3Packages; [
            setuptools
            wheel
	          beautifulsoup4
	        ];
          src = (pkgs.fetchFromGitHub {
            owner = "harrison-broadbent";
            repo = "libgen-api";
            rev = "v0.3.0";
            sha256 = "GwomZduHpF/vqT9h0kw9Df6bG0enGPWwDlvdKIS85Ww=";
        });};
      in
        pkgs.python3Packages.buildPythonPackage rec {
          pname = "getBook";
          version = "0.1.0";
          src = ./.;
          propagatedBuildInputs = with pkgs.python3Packages; [
            requests
            libgenApi
          ];
        };
  };
}

returns:

error: --- Error --- nix-daemon
builder for '/nix/store/jcpgpifbmjvc8rr8f2dglflad9m534i8-python3.8-libgen-api-0.3.0.drv' failed with exit code 1; last 10 log lines:
  warning: file source/setup.py may be generated; SOURCE_DATE_EPOCH may be non-deterministic
  patching sources
  configuring
  no configure script, doing nothing
  building
  Executing setuptoolsBuildPhase
  running bdist_wheel
  running build
  running build_py
  error: package directory 'libgen_api' does not exist
error: --- Error ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- nix
1 dependencies of derivation '/nix/store/x9ymy0xdx8afhl79plncliyc40kc106l-python3.8-getBook-0.1.0.drv' failed to build

Apparently, the project is pretty broken:

  • It uses API in directory name but api in setup.py
  • It uses bs4 instead of beautifulsoup4

The following seems to make it build:

pkgs.python3Packages.buildPythonPackage rec {
  pname = "libgen-api";
  version = "0.3.0";

  src = pkgs.fetchFromGitHub {
    owner = "harrison-broadbent";
    repo = "libgen-api";
    rev = "v${version}";
    sha256 = "GwomZduHpF/vqT9h0kw9Df6bG0enGPWwDlvdKIS85Ww=";
  };

  propagatedBuildInputs = with pkgs.python3Packages; [
    lxml
    requests
    beautifulsoup4
  ];

  postPatch = ''
    mv libgen_{API,api}
    substituteInPlace setup.py --replace "bs4" "beautifulsoup4"
  '';

  # There are no tests.
  doCheck = false;
}
3 Likes