-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdevenv.nix
More file actions
146 lines (137 loc) · 4.84 KB
/
Copy pathdevenv.nix
File metadata and controls
146 lines (137 loc) · 4.84 KB
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
{ config, inputs, lib, pkgs, ... }:
let
cfg = config.languages.python.uv2nix;
in {
options.languages.python = with lib; {
uv2nix = {
enable = mkEnableOption "uv2nix";
package = mkOption {
type = lib.types.package;
description = "The python package to use";
};
packages = mkOption {
type = with types; listOf package;
default = [];
description = "Packages to include on the same level as python (using this instead of packages could help with tools like pytest not working, for example you might put python tools there like pre-commit as they might mess up the environment)";
};
preferWheels = mkOption {
type = types.bool;
default = true;
description = "whther to prefer wheels over source packages";
};
root = mkOption {
type = types.path;
description = "root of the project";
};
projectFiles = mkOption {
type = with types; listOf path;
description = "list of files that make the project, so things don't have to be recomputed on every change";
default = [
(cfg.root + "/pyproject.toml")
];
};
extraDependencies = mkOption {
type = with types; attrsOf (listOf str);
description = "list of additional python dependencies";
default = {
editables = [];
};
};
buildSystemOverrides = mkOption {
type = with types; attrsOf (attrsOf (listOf str));
description = "build system overrides";
default = {};
};
overrides = mkOption {
type = types.unspecified;
description = "advanced overrides for packages";
default = self: super: {};
};
injectAppEnv = mkOption {
type = types.bool;
description = "include the app and its dependencies in the dev shell";
default = true;
};
impureEnv = mkOption {
type = types.bool;
description = "use env built by uv over uv2nix";
default = false;
};
};
};
config = let
lockExists = builtins.pathExists (cfg.root + "/uv.lock");
project = inputs.pyproject-nix.lib.project.loadPyproject {
projectRoot = cfg.root;
};
projectName = project.pyproject.project.name;
workspace = inputs.uv2nix.lib.workspace.loadWorkspace {
workspaceRoot = cfg.root;
};
overlay = workspace.mkPyprojectOverlay {
sourcePreference = if cfg.preferWheels then "wheel" else "sdist";
};
buildSystemOverrides = final: prev: builtins.mapAttrs (
name: spec:
prev.${name}.overrideAttrs (old: {
nativeBuildInputs = old.nativeBuildInputs ++ final.resolveBuildSystem spec;
})
) cfg.buildSystemOverrides;
pythonSet = (pkgs.callPackage inputs.pyproject-nix.build.packages {
python = cfg.package;
}).overrideScope (
lib.composeManyExtensions [
inputs.pyproject-build-systems.overlays.default
overlay
buildSystemOverrides
cfg.overrides
]
);
editableOverlay = workspace.mkEditablePyprojectOverlay {
root = "$DEVENV_ROOT";
# members = [ "hello-world" ];
};
editablePythonSet = pythonSet.overrideScope (
lib.composeManyExtensions [
editableOverlay
(final: prev: {
${projectName} = prev.${projectName}.overrideAttrs (old: {
src = lib.fileset.toSource {
root = cfg.root;
fileset = lib.fileset.unions cfg.projectFiles;
};
nativeBuildInputs = old.nativeBuildInputs ++ final.resolveBuildSystem cfg.extraDependencies;
});
})
]
);
app = pythonSet.mkVirtualEnv "${projectName}-env" workspace.deps.default;
env = editablePythonSet.mkVirtualEnv "${projectName}-dev-env" workspace.deps.all;
in lib.mkIf cfg.enable {
cachix.pull = [ "pyproject-nix" ];
env = {
# don't allow uv to download different python interpreters
UV_PYTHON_DOWNLOADS = "never";
}
// lib.optionalAttrs cfg.impureEnv (
{
# make uv use python provided by nix
UV_PYTHON = config.languages.python.package;
} // lib.optionalAttrs pkgs.stdenv.isLinux {
LD_LIBRARY_PATH = lib.makeLibraryPath pkgs.pythonManylinuxPackages.manylinux1;
}
)
// lib.optionalAttrs (!cfg.impureEnv) {
UV_NO_SYNC = "1";
UV_PYTHON = if lockExists then "${config.outputs.python.env}/bin/python" else "${config.languages.python.package}/bin/python";
};
languages.python.uv.package = lib.mkDefault inputs.uv2nix.packages.${pkgs.stdenv.targetPlatform.system}.uv-bin;
outputs.python = {
inherit app env editableOverlay editablePythonSet config;
};
packages = [
config.languages.python.uv.package
] ++ lib.optional (lockExists && cfg.injectAppEnv) config.outputs.python.env;
unsetEnvVars = ["PYTHONPATH"];
};
}