Skip to content
This repository was archived by the owner on Sep 1, 2025. It is now read-only.

Commit e17370e

Browse files
authored
Merge pull request #1148 from danmur97/main
feat(back): #1146 make python pyproject
2 parents 64eb23f + acf54c6 commit e17370e

11 files changed

Lines changed: 279 additions & 21 deletions

File tree

docs/src/api/extensions/python.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,114 @@ Example:
122122

123123
Refer to [makePythonLock](/api/builtins/utilities/#makepythonlock)
124124
to learn how to generate a `sourcesYaml`.
125+
126+
## makePythonPyprojectPackage
127+
128+
Create a python package bundle using nixpkgs build functions.
129+
This bundle includes the package itself, some modifications
130+
over the tests and its python environments.
131+
132+
Types:
133+
134+
- makePythonPypiEnvironment: (`function Input -> Bundle`):
135+
- Input: `AttrsOf`
136+
- buildEnv: `function {...} -> Derivation`
137+
The nixpkgs buildEnv.override function.
138+
Commonly found at `nixpkgs."${python_version}".buildEnv.override`
139+
- buildPythonPackage: `function {...} -> Derivation`
140+
The nixpkgs buildPythonPackage function.
141+
Commonly found at `nixpkgs."${python_version}".pkgs.buildPythonPackage`
142+
- pkgDeps: `AttrsOf`
143+
The package dependencies.
144+
Usually other python packages build with nix,
145+
but can be also a nix derivation of a binary.
146+
- runtime_deps: `List[Derivation]`
147+
- build_deps: `List[Derivation]`
148+
- test_deps: `List[Derivation]`
149+
- src: `NixPath`
150+
The nix path to the source code of the python package.
151+
i.e. not only be the package itself, it should also contain
152+
a tests folder/module, the pyproject conf and any other meta-package
153+
data that the build or tests requires (e.g. custom mypy conf).
154+
- Bundle: `AttrsOf`
155+
- check: `AttrsOf`
156+
Builds of the package only including one test.
157+
- tests:`Derivation`
158+
- types: `Derivation`
159+
- env: `AttrsOf`
160+
- dev: `Derivation`
161+
The python environment containing only
162+
runtime_deps and test_deps
163+
- runtime: `Derivation`
164+
The python environment containing only
165+
the package itself and its runtime_deps.
166+
- pkg: `Derivation`
167+
The output of the nixpkgs buildPythonPackage function
168+
i.e. the python package
169+
170+
???+ tip
171+
172+
The default implemented tests require `mypy` and `pytest` as `test_deps`.
173+
If you do not want the default, you can override the checkPhase
174+
of the package i.e. using `pythonOverrideUtils` or using the
175+
`overridePythonAttrs` function included on the derivation of
176+
nix built python packages.
177+
178+
Example:
179+
180+
=== "main.nix"
181+
182+
```nix
183+
# /path/to/my/project/makes/example/main.nix
184+
{
185+
inputs,
186+
makeScript,
187+
makePythonPyprojectPackage,
188+
...
189+
}: let
190+
nixpkgs = inputs.nixpkgs;
191+
python_version = "python311";
192+
python_pkgs = nixpkgs."${python_version}Packages";
193+
bundle = makePythonPyprojectPackage {
194+
src = ./.;
195+
buildEnv = nixpkgs."${python_version}".buildEnv.override;
196+
buildPythonPackage = nixpkgs."${python_version}".pkgs.buildPythonPackage;
197+
pkgDeps = {
198+
runtime_deps = with python_pkgs; [click];
199+
build_deps = with python_pkgs; [flit-core];
200+
test_deps = with python_pkgs; [
201+
mypy
202+
pytest
203+
];
204+
};
205+
};
206+
env = bundle.env.runtime;
207+
in
208+
makeScript {
209+
name = "my-cli";
210+
searchPaths = {
211+
bin = [
212+
env
213+
];
214+
};
215+
entrypoint = "my-cli \"\${@}\"";
216+
# Assuming that the pyproject conf has
217+
# a definition of `my-cli` as a cli entrypoint
218+
}
219+
```
220+
221+
???+ tip
222+
223+
Because env.runtime include the package,
224+
all tests are triggered when building the environment.
225+
If is desirable only to trigger an specific check phase,
226+
then use the check derivations that override this phase.
227+
228+
???+ tip
229+
230+
To avoid performance issues use a shared cache
231+
system (e.g. cachix) or an override over the package
232+
to skip tests (unsafe way) to ensure that tests are
233+
executed only once (or never).
234+
This can also help on performance over heavy
235+
compilation/build processes.

src/args/agnostic.nix

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
system ? builtins.currentSystem,
99
}: let
1010
fix' = __unfix__: let x = __unfix__ x // {inherit __unfix__;}; in x;
11-
12-
args = fix' (self: {
11+
sources = import ../nix/sources.nix;
12+
args = fix' (self: let
1313
__nixpkgs__ = import sources.nixpkgs {inherit system;};
14+
in {
15+
inherit __nixpkgs__;
1416
__nixpkgsSrc__ = sources.nixpkgs;
1517
__shellCommands__ = ./shell-commands/template.sh;
1618
__shellOptions__ = ./shell-options/template.sh;
@@ -19,27 +21,27 @@
1921
__toModuleOutputs__ = import ./to-module-outputs/default.nix self;
2022
asContent = import ./as-content/default.nix;
2123
attrsGet = import ./attrs-get/default.nix;
22-
attrsMapToList = self.__nixpkgs__.lib.mapAttrsToList;
23-
attrsMerge = builtins.foldl' self.__nixpkgs__.lib.recursiveUpdate {};
24-
attrsOptional = self.__nixpkgs__.lib.optionalAttrs;
24+
attrsMapToList = __nixpkgs__.lib.mapAttrsToList;
25+
attrsMerge = builtins.foldl' __nixpkgs__.lib.recursiveUpdate {};
26+
attrsOptional = __nixpkgs__.lib.optionalAttrs;
2527
calculateCvss3 = import ./calculate-cvss-3/default.nix self;
2628
calculateScorecard = import ./calculate-scorecard/default.nix self;
2729
chunks = import ./chunks/default.nix self;
2830
computeOnAwsBatch = import ./compute-on-aws-batch/default.nix self;
2931
deployContainerImage = import ./deploy-container-image/default.nix self;
3032
deployNomad = import ./deploy-nomad/default.nix self;
3133
deployTerraform = import ./deploy-terraform/default.nix self;
32-
inherit (self.__nixpkgs__.lib.strings) escapeShellArg;
33-
inherit (self.__nixpkgs__.lib.strings) escapeShellArgs;
34-
inherit (self.__nixpkgs__.lib) fakeSha256;
34+
inherit (__nixpkgs__.lib.strings) escapeShellArg;
35+
inherit (__nixpkgs__.lib.strings) escapeShellArgs;
36+
inherit (__nixpkgs__.lib) fakeSha256;
3537
fetchArchive = import ./fetch-archive/default.nix self;
3638
fetchGithub = import ./fetch-github/default.nix self;
3739
fetchGitlab = import ./fetch-gitlab/default.nix self;
3840
fetchNixpkgs = import ./fetch-nixpkgs/default.nix self;
3941
fetchRubyGem = import ./fetch-rubygem/default.nix self;
4042
fetchUrl = import ./fetch-url/default.nix self;
41-
inherit (self.__nixpkgs__.lib) filterAttrs;
42-
inherit (self.__nixpkgs__.lib.lists) flatten;
43+
inherit (__nixpkgs__.lib) filterAttrs;
44+
inherit (__nixpkgs__.lib.lists) flatten;
4345
formatBash = import ./format-bash/default.nix self;
4446
formatNix = import ./format-nix/default.nix self;
4547
formatPython = import ./format-python/default.nix self;
@@ -51,12 +53,12 @@
5153
fromYaml = import ./from-yaml/default.nix self;
5254
fromYamlFile = path: self.fromYaml (builtins.readFile path);
5355
gitlabCi = import ./gitlab-ci/default.nix;
54-
inherit (self.__nixpkgs__.lib.strings) hasPrefix;
55-
inherit (self.__nixpkgs__.lib.strings) hasSuffix;
56-
inherit (self.__nixpkgs__.stdenv) isDarwin;
57-
inherit (self.__nixpkgs__.stdenv) isLinux;
56+
inherit (__nixpkgs__.lib.strings) hasPrefix;
57+
inherit (__nixpkgs__.lib.strings) hasSuffix;
58+
inherit (__nixpkgs__.stdenv) isDarwin;
59+
inherit (__nixpkgs__.stdenv) isLinux;
5860
libGit = import ./lib-git/default.nix self;
59-
listOptional = self.__nixpkgs__.lib.lists.optional;
61+
listOptional = __nixpkgs__.lib.lists.optional;
6062
lintClojure = import ./lint-clojure/default.nix self;
6163
lintGitCommitMsg = import ./lint-git-commit-msg/default.nix self;
6264
lintGitMailMap = import ./lint-git-mailmap/default.nix self;
@@ -67,7 +69,7 @@
6769
lintTerraform = import ./lint-terraform/default.nix self;
6870
lintWithAjv = import ./lint-with-ajv/default.nix self;
6971
lintWithLizard = import ./lint-with-lizard/default.nix self;
70-
inherit (self.__nixpkgs__.lib.filesystem) listFilesRecursive;
72+
inherit (__nixpkgs__.lib.filesystem) listFilesRecursive;
7173
makeContainerImage = import ./make-container-image/default.nix self;
7274
makeDerivation = import ./make-derivation/default.nix self;
7375
makeDerivationParallel = import ./make-derivation-parallel/default.nix self;
@@ -79,6 +81,7 @@
7981
makeNodeJsVersion = import ./make-node-js-version/default.nix self;
8082
makeNomadEnvironment = import ./make-nomad-environment/default.nix self;
8183
makePythonPypiEnvironment = import ./make-python-pypi-environment/default.nix self;
84+
makePythonPyprojectPackage = import ./make-python-pyproject-package/default.nix;
8285
makePythonVersion = import ./make-python-version/default.nix self;
8386
makeRubyGemsEnvironment = import ./make-ruby-gems-environment/default.nix self;
8487
makeRubyGemsInstall = import ./make-ruby-gems-install/default.nix self;
@@ -99,19 +102,20 @@
99102
makeWorkspaceForTerraformFromEnv = import ./make-workspace-for-terraform-from-env/default.nix self;
100103
managePorts = import ./manage-ports/default.nix self;
101104
patchShebangs = import ./patch-shebangs/default.nix self;
102-
inherit (self.__nixpkgs__.lib) removePrefix;
105+
pythonOverrideUtils = import ./python-override-utils/default.nix;
106+
inherit (__nixpkgs__.lib) removePrefix;
103107
secureKubernetesWithRbacPolice = import ./secure-kubernetes-with-rbac-police/default.nix self;
104108
securePythonWithBandit = import ./secure-python-with-bandit/default.nix self;
105109
sortAscii = builtins.sort (a: b: a < b);
106-
sortAsciiCaseless = builtins.sort (a: b: self.__nixpkgs__.lib.toLower a < self.__nixpkgs__.lib.toLower b);
110+
sortAsciiCaseless = builtins.sort (a: b: __nixpkgs__.lib.toLower a < __nixpkgs__.lib.toLower b);
107111
stringCapitalize = import ./string-capitalize/default.nix self;
108112
sublist = import ./sublist/default.nix self;
109113
taintTerraform = import ./taint-terraform/default.nix self;
110114
testLicense = import ./test-license/default.nix self;
111115
testTerraform = import ./test-terraform/default.nix self;
112116
testPullRequest = import ./test-pull-request/default.nix self;
113117
testPython = import ./test-python/default.nix self;
114-
toDerivationName = self.__nixpkgs__.lib.strings.sanitizeDerivationName;
118+
toDerivationName = __nixpkgs__.lib.strings.sanitizeDerivationName;
115119
toBashArray = import ./to-bash-array/default.nix self;
116120
toBashMap = import ./to-bash-map/default.nix self;
117121
toFileJson = import ./to-file-json/default.nix self;
@@ -120,7 +124,5 @@
120124
toFileJsonFromFileYaml = import ./to-file-json-from-file-yaml/default.nix self;
121125
toFileLst = import ./to-file-lst/default.nix;
122126
});
123-
124-
sources = import ../nix/sources.nix;
125127
in
126128
assert args.isDarwin || args.isLinux; args
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
buildEnv,
3+
buildPythonPackage,
4+
pkgDeps,
5+
src,
6+
}:
7+
import ./generic_builder {
8+
inherit buildEnv buildPythonPackage pkgDeps src;
9+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{pkg}: let
2+
build_check = check:
3+
pkg.overridePythonAttrs (
4+
old: {
5+
checkPhase = [old."${check}"];
6+
}
7+
);
8+
in {
9+
tests = build_check "test_check";
10+
types = build_check "type_check";
11+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
buildEnv,
3+
buildPythonPackage,
4+
pkgDeps,
5+
src,
6+
}: let
7+
metadata = import ./metadata.nix src;
8+
pkg = import ./pkg {
9+
inherit buildPythonPackage metadata pkgDeps src;
10+
};
11+
env = import ./env.nix {
12+
inherit buildEnv pkgDeps pkg;
13+
};
14+
checks = import ./check.nix {inherit pkg;};
15+
in {
16+
inherit pkg env;
17+
check = checks;
18+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
buildEnv,
3+
pkgDeps,
4+
pkg,
5+
}: let
6+
build_env = extraLibs:
7+
buildEnv {
8+
inherit extraLibs;
9+
ignoreCollisions = false;
10+
};
11+
in {
12+
runtime = build_env [pkg];
13+
dev = build_env (pkgDeps.runtime_deps ++ pkgDeps.test_deps);
14+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
src: let
2+
_metadata = (builtins.fromTOML (builtins.readFile "${src}/pyproject.toml")).project;
3+
file_str = builtins.readFile "${src}/${_metadata.name}/__init__.py";
4+
match = builtins.match ".*__version__ *= *\"(.+)\"\n.*" file_str;
5+
version = builtins.elemAt match 0;
6+
in
7+
_metadata // {inherit version;}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# shellcheck shell=bash
2+
3+
echo "Executing test phase" \
4+
&& pytest --version \
5+
&& pytest ./tests \
6+
&& echo "Finished test phase"
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# shellcheck shell=bash
2+
3+
echo "Executing type check phase" \
4+
&& mypy --version \
5+
&& mypy . --config-file ./mypy.ini \
6+
&& echo "Finished type check phase"
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
buildPythonPackage,
3+
metadata,
4+
pkgDeps,
5+
src,
6+
}: let
7+
type_check = ./check/types.sh;
8+
test_check = ./check/tests.sh;
9+
in
10+
buildPythonPackage {
11+
inherit src type_check test_check;
12+
inherit (metadata) version;
13+
pname = metadata.name;
14+
format = "pyproject";
15+
checkPhase = [
16+
''
17+
source ${type_check} \
18+
&& source ${test_check} \
19+
''
20+
];
21+
doCheck = true;
22+
pythonImportsCheck = [metadata.name];
23+
nativeBuildInputs = pkgDeps.build_deps;
24+
propagatedBuildInputs = pkgDeps.runtime_deps;
25+
nativeCheckInputs = pkgDeps.test_deps;
26+
}

0 commit comments

Comments
 (0)