1# Tests for the Python interpreters, package sets and environments.
2#
3# Each Python interpreter has a `passthru.tests` which is the attribute set
4# returned by this function. For example, for Python 3 the tests are run with
5#
6# $ nix-build -A python3.tests
7#
8{ stdenv
9, python
10, runCommand
11, substituteAll
12, lib
13, callPackage
14}:
15
16let
17 # Test whether the interpreter behaves in the different types of environments
18 # we aim to support.
19 environmentTests = let
20 envs = let
21 inherit python;
22 pythonEnv = python.withPackages(ps: with ps; [ ]);
23 pythonVirtualEnv = python.withPackages(ps: with ps; [ virtualenv ]);
24 in {
25 # Plain Python interpreter
26 plain = rec {
27 env = python;
28 interpreter = env.interpreter;
29 is_venv = "False";
30 is_nixenv = "False";
31 is_virtualenv = "False";
32 };
33 } // lib.optionalAttrs (!python.isPyPy) {
34 # Use virtualenv from a Nix env.
35 nixenv-virtualenv = rec {
36 env = runCommand "${python.name}-virtualenv" {} ''
37 ${pythonVirtualEnv.interpreter} -m virtualenv $out
38 '';
39 interpreter = "${env}/bin/${python.executable}";
40 is_venv = "False";
41 is_nixenv = "True";
42 is_virtualenv = "True";
43 };
44 } // lib.optionalAttrs (python.implementation != "graal") {
45 # Python Nix environment (python.buildEnv)
46 nixenv = rec {
47 env = pythonEnv;
48 interpreter = env.interpreter;
49 is_venv = "False";
50 is_nixenv = "True";
51 is_virtualenv = "False";
52 };
53 } // lib.optionalAttrs (python.isPy3k && (!python.isPyPy)) rec {
54 # Venv built using plain Python
55 # Python 2 does not support venv
56 # TODO: PyPy executable name is incorrect, it should be pypy-c or pypy-3c instead of pypy and pypy3.
57 plain-venv = rec {
58 env = runCommand "${python.name}-venv" {} ''
59 ${python.interpreter} -m venv $out
60 '';
61 interpreter = "${env}/bin/${python.executable}";
62 is_venv = "True";
63 is_nixenv = "False";
64 is_virtualenv = "False";
65 };
66
67 } // lib.optionalAttrs (python.pythonAtLeast "3.8") {
68 # Venv built using Python Nix environment (python.buildEnv)
69 # TODO: Cannot create venv from a nix env
70 # Error: Command '['/nix/store/ddc8nqx73pda86ibvhzdmvdsqmwnbjf7-python3-3.7.6-venv/bin/python3.7', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1.
71 nixenv-venv = rec {
72 env = runCommand "${python.name}-venv" {} ''
73 ${pythonEnv.interpreter} -m venv $out
74 '';
75 interpreter = "${env}/bin/${pythonEnv.executable}";
76 is_venv = "True";
77 is_nixenv = "True";
78 is_virtualenv = "False";
79 };
80 };
81
82 testfun = name: attrs: runCommand "${python.name}-tests-${name}" ({
83 inherit (python) pythonVersion;
84 } // attrs) ''
85 cp -r ${./tests/test_environments} tests
86 chmod -R +w tests
87 substituteAllInPlace tests/test_python.py
88 ${attrs.interpreter} -m unittest discover --verbose tests #/test_python.py
89 mkdir $out
90 touch $out/success
91 '';
92
93 in lib.mapAttrs testfun envs;
94
95 # Integration tests involving the package set.
96 # All PyPy package builds are broken at the moment
97 integrationTests = lib.optionalAttrs (!python.isPyPy) (
98 lib.optionalAttrs (python.isPy3k && !stdenv.isDarwin) { # darwin has no split-debug
99 cpython-gdb = callPackage ./tests/test_cpython_gdb {
100 interpreter = python;
101 };
102 } // lib.optionalAttrs (python.pythonAtLeast "3.7") rec {
103 # Before the addition of NIX_PYTHONPREFIX mypy was broken with typed packages
104 nix-pythonprefix-mypy = callPackage ./tests/test_nix_pythonprefix {
105 interpreter = python;
106 };
107 }
108 );
109
110 # Tests to ensure overriding works as expected.
111 overrideTests = let
112 extension = self: super: {
113 foobar = super.numpy;
114 };
115 in {
116 test-packageOverrides = let
117 myPython = let
118 self = python.override {
119 packageOverrides = extension;
120 inherit self;
121 };
122 in self;
123 in assert myPython.pkgs.foobar == myPython.pkgs.numpy; myPython.withPackages(ps: with ps; [ foobar ]);
124 # overrideScope is broken currently
125 # test-overrideScope = let
126 # myPackages = python.pkgs.overrideScope extension;
127 # in assert myPackages.foobar == myPackages.numpy; myPackages.python.withPackages(ps: with ps; [ foobar ]);
128 };
129
130 condaTests = let
131 requests = callPackage ({
132 autoPatchelfHook,
133 fetchurl,
134 pythonCondaPackages,
135 }:
136 python.pkgs.buildPythonPackage {
137 pname = "requests";
138 version = "2.24.0";
139 format = "other";
140 src = fetchurl {
141 url = "https://repo.anaconda.com/pkgs/main/noarch/requests-2.24.0-py_0.tar.bz2";
142 sha256 = "02qzaf6gwsqbcs69pix1fnjxzgnngwzvrsy65h1d521g750mjvvp";
143 };
144 nativeBuildInputs = [ autoPatchelfHook ] ++ (with python.pkgs; [
145 condaUnpackHook condaInstallHook
146 ]);
147 buildInputs = [
148 pythonCondaPackages.condaPatchelfLibs
149 ];
150 propagatedBuildInputs = with python.pkgs; [
151 chardet idna urllib3 certifi
152 ];
153 }
154 ) {};
155 pythonWithRequests = requests.pythonModule.withPackages (ps: [ requests ]);
156 in
157 {
158 condaExamplePackage = runCommand "import-requests" {} ''
159 ${pythonWithRequests.interpreter} -c "import requests" > $out
160 '';
161 };
162
163in lib.optionalAttrs (stdenv.hostPlatform == stdenv.buildPlatform ) (environmentTests // integrationTests // overrideTests // condaTests)