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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
|
{
pkgs,
stdenv,
lib,
python,
}:
self:
let
inherit (self) callPackage;
namePrefix = python.libPrefix + "-";
# Derivations built with `buildPythonPackage` can already be overridden with `override`, `overrideAttrs`, and `overrideDerivation`.
# This function introduces `overridePythonAttrs` and it overrides the call to `buildPythonPackage`.
#
# Overridings specified through `overridePythonAttrs` will always be applied
# before those specified by `overrideAttrs`, even if invoked after them.
makeOverridablePythonPackage =
f:
lib.mirrorFunctionArgs f (
origArgs:
let
result = f origArgs;
overrideWith =
if lib.isFunction origArgs then
newArgs: lib.extends (_: lib.toFunction newArgs) origArgs
else
newArgs: origArgs // lib.toFunction newArgs origArgs;
in
if lib.isAttrs result then
result
// {
overridePythonAttrs = newArgs: makeOverridablePythonPackage f (overrideWith newArgs);
overrideAttrs =
newArgs: makeOverridablePythonPackage (args: (f args).overrideAttrs newArgs) origArgs;
}
else
result
)
// {
# Support overriding `f` itself, e.g. `buildPythonPackage.override { }`.
# Ensure `makeOverridablePythonPackage` is applied to the result.
override = lib.mirrorFunctionArgs f.override (
newArgs: makeOverridablePythonPackage (f.override newArgs)
);
};
overrideStdenvCompat =
f:
lib.fix (
f':
lib.mirrorFunctionArgs f (
args:
let
result = f args;
getName = x: x.pname or (lib.getName (x.name or "<unnamed>"));
applyMsgStdenvArg =
name:
lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2511) ''
${name}: Passing `stdenv` directly to `buildPythonPackage` or `buildPythonApplication` is deprecated. You should use their `.override` function instead, e.g:
buildPythonPackage.override { stdenv = customStdenv; } { }
'';
in
if lib.isFunction args && result ? __stdenvPythonCompat then
# Less reliable, as constructing with the wrong `stdenv` might lead to evaluation errors in the package definition.
f'.override { stdenv = applyMsgStdenvArg (getName result) result.__stdenvPythonCompat; } (
finalAttrs: removeAttrs (args finalAttrs) [ "stdenv" ]
)
else if (!lib.isFunction args) && (args ? stdenv) then
# More reliable, but only works when args is not `(finalAttrs: { })`
f'.override { stdenv = applyMsgStdenvArg (getName args) args.stdenv; } (
removeAttrs args [ "stdenv" ]
)
else
result
)
// {
# Preserve the effect of overrideStdenvCompat when calling `buildPython*.override`.
override = lib.mirrorFunctionArgs f.override (newArgs: overrideStdenvCompat (f.override newArgs));
}
);
mkPythonDerivation =
if python.isPy3k then ./mk-python-derivation.nix else ./python2/mk-python-derivation.nix;
buildPythonPackage = makeOverridablePythonPackage (
overrideStdenvCompat (
callPackage mkPythonDerivation {
inherit namePrefix; # We want Python libraries to be named like e.g. "python3.6-${name}"
inherit toPythonModule; # Libraries provide modules
inherit (python) stdenv;
}
)
);
buildPythonApplication = makeOverridablePythonPackage (
overrideStdenvCompat (
callPackage mkPythonDerivation {
namePrefix = ""; # Python applications should not have any prefix
toPythonModule = x: x; # Application does not provide modules.
inherit (python) stdenv;
}
)
);
# Check whether a derivation provides a Python module.
hasPythonModule = drv: drv ? pythonModule && drv.pythonModule == python;
# Get list of required Python modules given a list of derivations.
requiredPythonModules =
drvs:
let
modules = lib.filter hasPythonModule drvs;
in
lib.unique (
[ python ] ++ modules ++ lib.concatLists (lib.catAttrs "requiredPythonModules" modules)
);
# Create a PYTHONPATH from a list of derivations. This function recurses into the items to find derivations
# providing Python modules.
makePythonPath = drvs: lib.makeSearchPath python.sitePackages (requiredPythonModules drvs);
removePythonPrefix = lib.removePrefix namePrefix;
mkPythonEditablePackage = callPackage ./editable.nix { };
mkPythonMetaPackage = callPackage ./meta-package.nix { };
# Convert derivation to a Python module.
toPythonModule =
drv:
drv.overrideAttrs (oldAttrs: {
# Use passthru in order to prevent rebuilds when possible.
passthru = (oldAttrs.passthru or { }) // {
pythonModule = python;
pythonPath = [ ]; # Deprecated, for compatibility.
requiredPythonModules = builtins.addErrorContext "while calculating requiredPythonModules for ${drv.name or drv.pname}:" (
requiredPythonModules drv.propagatedBuildInputs
);
};
});
# Convert a Python library to an application.
toPythonApplication =
drv:
drv.overrideAttrs (oldAttrs: {
passthru = (oldAttrs.passthru or { }) // {
# Remove Python prefix from name so we have a "normal" name.
# While the prefix shows up in the store path, it won't be
# used by `nix-env`.
name = removePythonPrefix oldAttrs.name;
pythonModule = false;
};
});
disabled =
drv:
throw "${
removePythonPrefix (drv.pname or drv.name)
} not supported for interpreter ${python.executable}";
disabledIf = x: drv: if x then disabled drv else drv;
in
{
inherit lib pkgs stdenv;
inherit (python.passthru)
isPy27
isPy37
isPy38
isPy39
isPy310
isPy311
isPy312
isPy313
isPy314
isPy3k
isPyPy
pythonAtLeast
pythonOlder
;
inherit buildPythonPackage buildPythonApplication;
inherit
hasPythonModule
requiredPythonModules
makePythonPath
disabled
disabledIf
;
inherit toPythonModule toPythonApplication;
inherit mkPythonMetaPackage mkPythonEditablePackage;
python = toPythonModule python;
# Don't take pythonPackages from "global" pkgs scope to avoid mixing python versions.
pythonPackages = self;
}
|