summary refs log tree commit diff
path: root/pkgs/development/tools/poetry2nix/poetry2nix/mk-poetry-dep.nix
blob: 95543ca73590972d8b9d2ed62576863bea387e3a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
{ autoPatchelfHook
, pkgs
, lib
, python
, buildPythonPackage
, pythonPackages
, poetryLib
}:
{ name
, version
, files
, source
, dependencies ? {}
, pythonPackages
, python-versions
, pwd
, supportedExtensions ? lib.importJSON ./extensions.json
, ...
}:

pythonPackages.callPackage (
  { preferWheel ? false
  }:

    let

      inherit (poetryLib) isCompatible getManyLinuxDeps fetchFromPypi;

      inherit (import ./pep425.nix {
        inherit lib python;
        inherit (pkgs) stdenv;
      }) selectWheel
        ;

      fileCandidates = let
        supportedRegex = ("^.*?(" + builtins.concatStringsSep "|" supportedExtensions + ")");
        matchesVersion = fname: builtins.match ("^.*" + builtins.replaceStrings [ "." ] [ "\\." ] version + ".*$") fname != null;
        hasSupportedExtension = fname: builtins.match supportedRegex fname != null;
        isCompatibleEgg = fname: ! lib.strings.hasSuffix ".egg" fname || lib.strings.hasSuffix "py${python.pythonVersion}.egg" fname;
      in
        builtins.filter (f: matchesVersion f.file && hasSupportedExtension f.file && isCompatibleEgg f.file) files;

      toPath = s: pwd + "/${s}";

      isSource = source != null;
      isGit = isSource && source.type == "git";
      isLocal = isSource && source.type == "directory";

      localDepPath = toPath source.url;
      pyProject = poetryLib.readTOML (localDepPath + "/pyproject.toml");

      buildSystemPkgs = poetryLib.getBuildSystemPkgs {
        inherit pythonPackages pyProject;
      };

      fileInfo = let
        isBdist = f: lib.strings.hasSuffix "whl" f.file;
        isSdist = f: ! isBdist f && ! isEgg f;
        isEgg = f: lib.strings.hasSuffix ".egg" f.file;

        binaryDist = selectWheel fileCandidates;
        sourceDist = builtins.filter isSdist fileCandidates;
        eggs = builtins.filter isEgg fileCandidates;

        entries = (if preferWheel then binaryDist ++ sourceDist else sourceDist ++ binaryDist) ++ eggs;

        lockFileEntry = builtins.head entries;

        _isEgg = isEgg lockFileEntry;

      in
        rec {
          inherit (lockFileEntry) file hash;
          name = file;
          format =
            if _isEgg then "egg"
            else if lib.strings.hasSuffix ".whl" name then "wheel"
            else "setuptools";
          kind =
            if _isEgg then python.pythonVersion
            else if format == "setuptools" then "source"
            else (builtins.elemAt (lib.strings.splitString "-" name) 2);
        };

      baseBuildInputs = lib.optional (name != "setuptools_scm" && name != "setuptools-scm") pythonPackages.setuptools_scm;

    in

      buildPythonPackage {
        pname = name;
        version = version;

        doCheck = false; # We never get development deps
        dontStrip = true;
        format = if isLocal then "pyproject" else if isGit then "setuptools" else fileInfo.format;

        nativeBuildInputs = if (!isSource && (getManyLinuxDeps fileInfo.name).str != null) then [ autoPatchelfHook ] else [];
        buildInputs = baseBuildInputs ++ (if !isSource then (getManyLinuxDeps fileInfo.name).pkg else []);

        propagatedBuildInputs =
          let
            # Some dependencies like django gets the attribute name django
            # but dependencies try to access Django
            deps = builtins.map (d: lib.toLower d) (builtins.attrNames dependencies);
          in
            (builtins.map (n: pythonPackages.${n}) deps) ++ (if isLocal then buildSystemPkgs else []);

        meta = {
          broken = ! isCompatible python.version python-versions;
          license = [];
        };

        # We need to retrieve kind from the interpreter and the filename of the package
        # Interpreters should declare what wheel types they're compatible with (python type + ABI)
        # Here we can then choose a file based on that info.
        src = if isGit then (
          builtins.fetchGit {
            inherit (source) url;
            rev = source.reference;
          }
        ) else if isLocal then (localDepPath) else fetchFromPypi {
          pname = name;
          inherit (fileInfo) file hash kind;
        };
      }

) {}