Python dev env with backports.cached_property

Hi! I’m trying to build a reproducible environment for Python based Robotframework tool and specifically its Browser library.

I’m trying to use Python 3.8 packages in my default.nix. However, Browser tries to be friendly to 3.7 users as well and they have

from backports.cached_property import cached_property

in the code, and then mark that little bit as a dependency in requirements.txt.

Basically what I have should suffice since I’m building with 3.8 and the cached_property feature is native in there. How do I tell Nix it isn’t needed? :slight_smile:

Here is my draft default.nix that I try out with nix-build without success:

with import <nixpkgs> {};    #  to my understanding refers to https://nixos.org/channels/nixos-20.09

python38Packages.buildPythonPackage {
    pname = "robotframework-browser";
    version = "5.0.0";

    src = ./.;

    propagatedBuildInputs = with python38Packages; [
      wrapt
      nodejs
    ];

    doCheck = false;
}

If they have this in the code without some type of try: ... catch:... then it’s not a conditional dependency, and you’ll need to bring it in regardless. Otherwise python will throw an ImportError regardless if the backports package is needed for a given python interpreter.

You can inspect the interpreter version, and conditional bring in dependencies

  # bring in dependencies for python <= 3.7
  propagatedBuildInputs = lib.optionals (python38.pythonOlder "3.8") [
    backports_csv
  ];

If you’re just iterating locally, then I would look at https://github.com/NixOS/nixpkgs/blob/f188138af3ebfd2f4d3c87f591b23b98396424f9/doc/languages-frameworks/python.section.md#how-to-consume-python-modules-using-pip-in-a-virtual-environment-like-i-am-used-to-on-other-operating-systems

Also, my video on python packaging with nix may be insightful. https://www.youtube.com/watch?v=jXd-hkP4xnU

Thank you! Very helpful. Did not get it to fully work yet but learned something new:) I did watch your video yesterday.

Improved my draft default.nix for browser library to this:

{ lib, buildPythonPackage }: 
#import (builtins.fetchTarball {
#  name = "nixpkgs-20.09-2021-05-27";
#  url = "https://releases.nixos.org/nixpkgs/20.09-darwin/nixpkgs-darwin-20.09pre246969.05f3800b80f/nixexprs.tar.xz";
#  sha256 = "0ah4fadrn8zr5m79xzn94z04hdc2y5r5g6i6h7pc90bqs2pscfjl"; }) {}

buildPythonPackage rec {
    pname = "robotframework-browser";
    version = "5.0.0";

    src = ./.;
     
    propagatedBuildInputs = with python3Packages; [
      wrapt
      nodejs
    ] ++ lib.optionals (python38.pythonOlder "3.8") [ backports.cached_property ];

    doCheck = false;
}

That seems to get quite far, until it does not find the backports.cached_property

I wrote a default.nix for backports.cached_property. It seems to me as the most vanilla thing you can have in Nix, but still I get an error when I run

nix-build -E 'with import <nixpkgs> {}; callPackage ./default.nix {}'

This is the backports.cached_property default.nix:

{ lib, buildPythonPackage, fetchFromGitHub }:
  
buildPythonPackage rec {
  pname = "backports.cached_property";
  version = "1.0.1";

  src = fetchFromGitHub {
    owner = "penguinolog";
    repo = pname;
    rev = version;
    sha256 = "04p1h1a1iv1lplg5inhzsw8qyxzsa3xbgsh6yf8q65dh21fvxmi4";
  };

  doCheck = false;

  meta = with lib; {
    description = "Backport of functools.cached_property";
    homepage = "https://github.com/penguinolog/backports.cached_property";
    license = lib.licenses.mit;
  };
}

The error message is:

error: anonymous function at /home/sukkeli/code/testing_backport_thing/default.nix:1:1 called without required argument 'buildPythonPackage', at /nix/store/zfrb5cgghvbhx7jw1zaqvz57zix3cfaq-nixos-20.09.4169.ac60476ed94/nixos/lib/customisation.nix:69:16

buildPythonPackage comes from the python package set. E.g. python38Packages or python38.pkgs (they are aliased)

1 Like