1# Python {#python}
2
3## User Guide {#user-guide}
4
5### Using Python {#using-python}
6
7#### Overview {#overview}
8
9Several versions of the Python interpreter are available on Nix, as well as a
10high amount of packages. The attribute `python3` refers to the default
11interpreter, which is currently CPython 3.10. The attribute `python` refers to
12CPython 2.7 for backwards-compatibility. It is also possible to refer to
13specific versions, e.g. `python311` refers to CPython 3.11, and `pypy` refers to
14the default PyPy interpreter.
15
16Python is used a lot, and in different ways. This affects also how it is
17packaged. In the case of Python on Nix, an important distinction is made between
18whether the package is considered primarily an application, or whether it should
19be used as a library, i.e., of primary interest are the modules in
20`site-packages` that should be importable.
21
22In the Nixpkgs tree Python applications can be found throughout, depending on
23what they do, and are called from the main package set. Python libraries,
24however, are in separate sets, with one set per interpreter version.
25
26The interpreters have several common attributes. One of these attributes is
27`pkgs`, which is a package set of Python libraries for this specific
28interpreter. E.g., the `toolz` package corresponding to the default interpreter
29is `python.pkgs.toolz`, and the CPython 3.11 version is `python311.pkgs.toolz`.
30The main package set contains aliases to these package sets, e.g.
31`pythonPackages` refers to `python.pkgs` and `python311Packages` to
32`python311.pkgs`.
33
34#### Installing Python and packages {#installing-python-and-packages}
35
36The Nix and NixOS manuals explain how packages are generally installed. In the
37case of Python and Nix, it is important to make a distinction between whether the
38package is considered an application or a library.
39
40Applications on Nix are typically installed into your user profile imperatively
41using `nix-env -i`, and on NixOS declaratively by adding the package name to
42`environment.systemPackages` in `/etc/nixos/configuration.nix`. Dependencies
43such as libraries are automatically installed and should not be installed
44explicitly.
45
46The same goes for Python applications. Python applications can be installed in
47your profile, and will be wrapped to find their exact library dependencies,
48without impacting other applications or polluting your user environment.
49
50But Python libraries you would like to use for development cannot be installed,
51at least not individually, because they won't be able to find each other
52resulting in import errors. Instead, it is possible to create an environment
53with `python.buildEnv` or `python.withPackages` where the interpreter and other
54executables are wrapped to be able to find each other and all of the modules.
55
56In the following examples we will start by creating a simple, ad-hoc environment
57with a nix-shell that has `numpy` and `toolz` in Python 3.11; then we will create
58a re-usable environment in a single-file Python script; then we will create a
59full Python environment for development with this same environment.
60
61Philosophically, this should be familiar to users who are used to a `venv` style
62of development: individual projects create their own Python environments without
63impacting the global environment or each other.
64
65#### Ad-hoc temporary Python environment with `nix-shell` {#ad-hoc-temporary-python-environment-with-nix-shell}
66
67The simplest way to start playing with the way nix wraps and sets up Python
68environments is with `nix-shell` at the cmdline. These environments create a
69temporary shell session with a Python and a *precise* list of packages (plus
70their runtime dependencies), with no other Python packages in the Python
71interpreter's scope.
72
73To create a Python 3.11 session with `numpy` and `toolz` available, run:
74
75```sh
76$ nix-shell -p 'python311.withPackages(ps: with ps; [ numpy toolz ])'
77```
78
79By default `nix-shell` will start a `bash` session with this interpreter in our
80`PATH`, so if we then run:
81
82```Python console
83[nix-shell:~/src/nixpkgs]$ python3
84Python 3.11.3 (main, Apr 4 2023, 22:36:41) [GCC 12.2.0] on linux
85Type "help", "copyright", "credits" or "license" for more information.
86>>> import numpy; import toolz
87```
88
89Note that no other modules are in scope, even if they were imperatively
90installed into our user environment as a dependency of a Python application:
91
92```Python console
93>>> import requests
94Traceback (most recent call last):
95 File "<stdin>", line 1, in <module>
96ModuleNotFoundError: No module named 'requests'
97```
98
99We can add as many additional modules onto the `nix-shell` as we need, and we
100will still get 1 wrapped Python interpreter. We can start the interpreter
101directly like so:
102
103```sh
104$ nix-shell -p "python311.withPackages (ps: with ps; [ numpy toolz requests ])" --run python3
105this derivation will be built:
106 /nix/store/r19yf5qgfiakqlhkgjahbg3zg79549n4-python3-3.11.2-env.drv
107building '/nix/store/r19yf5qgfiakqlhkgjahbg3zg79549n4-python3-3.11.2-env.drv'...
108created 273 symlinks in user environment
109Python 3.11.2 (main, Feb 7 2023, 13:52:42) [GCC 12.2.0] on linux
110Type "help", "copyright", "credits" or "license" for more information.
111>>> import requests
112>>>
113```
114
115Notice that this time it built a new Python environment, which now includes
116`requests`. Building an environment just creates wrapper scripts that expose the
117selected dependencies to the interpreter while re-using the actual modules. This
118means if any other env has installed `requests` or `numpy` in a different
119context, we don't need to recompile them -- we just recompile the wrapper script
120that sets up an interpreter pointing to them. This matters much more for "big"
121modules like `pytorch` or `tensorflow`.
122
123Module names usually match their names on [pypi.org](https://pypi.org/), but
124you can use the [Nixpkgs search website](https://nixos.org/nixos/packages.html)
125to find them as well (along with non-python packages).
126
127At this point we can create throwaway experimental Python environments with
128arbitrary dependencies. This is a good way to get a feel for how the Python
129interpreter and dependencies work in Nix and NixOS, but to do some actual
130development, we'll want to make it a bit more persistent.
131
132##### Running Python scripts and using `nix-shell` as shebang {#running-python-scripts-and-using-nix-shell-as-shebang}
133
134Sometimes, we have a script whose header looks like this:
135
136```python
137#!/usr/bin/env python3
138import numpy as np
139a = np.array([1,2])
140b = np.array([3,4])
141print(f"The dot product of {a} and {b} is: {np.dot(a, b)}")
142```
143
144Executing this script requires a `python3` that has `numpy`. Using what we learned
145in the previous section, we could startup a shell and just run it like so:
146
147```ShellSession
148$ nix-shell -p 'python311.withPackages (ps: with ps; [ numpy ])' --run 'python3 foo.py'
149The dot product of [1 2] and [3 4] is: 11
150```
151
152But if we maintain the script ourselves, and if there are more dependencies, it
153may be nice to encode those dependencies in source to make the script re-usable
154without that bit of knowledge. That can be done by using `nix-shell` as a
155[shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)), like so:
156
157```python
158#!/usr/bin/env nix-shell
159#!nix-shell -i python3 -p "python3.withPackages(ps: [ ps.numpy ])"
160import numpy as np
161a = np.array([1,2])
162b = np.array([3,4])
163print(f"The dot product of {a} and {b} is: {np.dot(a, b)}")
164```
165
166Then we simply execute it, without requiring any environment setup at all!
167
168```sh
169$ ./foo.py
170The dot product of [1 2] and [3 4] is: 11
171```
172
173If the dependencies are not available on the host where `foo.py` is executed, it
174will build or download them from a Nix binary cache prior to starting up, prior
175that it is executed on a machine with a multi-user nix installation.
176
177This provides a way to ship a self bootstrapping Python script, akin to a
178statically linked binary, where it can be run on any machine (provided nix is
179installed) without having to assume that `numpy` is installed globally on the
180system.
181
182By default it is pulling the import checkout of Nixpkgs itself from our nix
183channel, which is nice as it cache aligns with our other package builds, but we
184can make it fully reproducible by pinning the `nixpkgs` import:
185
186```python
187#!/usr/bin/env nix-shell
188#!nix-shell -i python3 -p "python3.withPackages (ps: [ ps.numpy ])"
189#!nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/e51209796c4262bfb8908e3d6d72302fe4e96f5f.tar.gz
190import numpy as np
191a = np.array([1,2])
192b = np.array([3,4])
193print(f"The dot product of {a} and {b} is: {np.dot(a, b)}")
194```
195
196This will execute with the exact same versions of Python 3.10, numpy, and system
197dependencies a year from now as it does today, because it will always use
198exactly git commit `e51209796c4262bfb8908e3d6d72302fe4e96f5f` of Nixpkgs for all
199of the package versions.
200
201This is also a great way to ensure the script executes identically on different
202servers.
203
204##### Load environment from `.nix` expression {#load-environment-from-.nix-expression}
205
206We've now seen how to create an ad-hoc temporary shell session, and how to
207create a single script with Python dependencies, but in the course of normal
208development we're usually working in an entire package repository.
209
210As explained in the Nix manual, `nix-shell` can also load an expression from a
211`.nix` file. Say we want to have Python 3.11, `numpy` and `toolz`, like before,
212in an environment. We can add a `shell.nix` file describing our dependencies:
213
214```nix
215with import <nixpkgs> {};
216(python311.withPackages (ps: with ps; [
217 numpy
218 toolz
219])).env
220```
221
222And then at the command line, just typing `nix-shell` produces the same
223environment as before. In a normal project, we'll likely have many more
224dependencies; this can provide a way for developers to share the environments
225with each other and with CI builders.
226
227What's happening here?
228
2291. We begin with importing the Nix Packages collections. `import <nixpkgs>`
230 imports the `<nixpkgs>` function, `{}` calls it and the `with` statement
231 brings all attributes of `nixpkgs` in the local scope. These attributes form
232 the main package set.
2332. Then we create a Python 3.11 environment with the `withPackages` function, as before.
2343. The `withPackages` function expects us to provide a function as an argument
235 that takes the set of all Python packages and returns a list of packages to
236 include in the environment. Here, we select the packages `numpy` and `toolz`
237 from the package set.
238
239To combine this with `mkShell` you can:
240
241```nix
242with import <nixpkgs> {};
243let
244 pythonEnv = python311.withPackages (ps: [
245 ps.numpy
246 ps.toolz
247 ]);
248in mkShell {
249 packages = [
250 pythonEnv
251
252 black
253 mypy
254
255 libffi
256 openssl
257 ];
258}
259```
260
261This will create a unified environment that has not just our Python interpreter
262and its Python dependencies, but also tools like `black` or `mypy` and libraries
263like `libffi` the `openssl` in scope. This is generic and can span any number of
264tools or languages across the Nixpkgs ecosystem.
265
266##### Installing environments globally on the system {#installing-environments-globally-on-the-system}
267
268Up to now, we've been creating environments scoped to an ad-hoc shell session,
269or a single script, or a single project. This is generally advisable, as it
270avoids pollution across contexts.
271
272However, sometimes we know we will often want a Python with some basic packages,
273and want this available without having to enter into a shell or build context.
274This can be useful to have things like vim/emacs editors and plugins or shell
275tools "just work" without having to set them up, or when running other software
276that expects packages to be installed globally.
277
278To create your own custom environment, create a file in `~/.config/nixpkgs/overlays/`
279that looks like this:
280
281```nix
282# ~/.config/nixpkgs/overlays/myEnv.nix
283self: super: {
284 myEnv = super.buildEnv {
285 name = "myEnv";
286 paths = [
287 # A Python 3 interpreter with some packages
288 (self.python3.withPackages (
289 ps: with ps; [
290 pyflakes
291 pytest
292 black
293 ]
294 ))
295
296 # Some other packages we'd like as part of this env
297 self.mypy
298 self.black
299 self.ripgrep
300 self.tmux
301 ];
302 };
303}
304```
305
306You can then build and install this to your profile with:
307
308```sh
309nix-env -iA myEnv
310```
311
312One limitation of this is that you can only have 1 Python env installed
313globally, since they conflict on the `python` to load out of your `PATH`.
314
315If you get a conflict or prefer to keep the setup clean, you can have `nix-env`
316atomically *uninstall* all other imperatively installed packages and replace
317your profile with just `myEnv` by using the `--replace` flag.
318
319##### Environment defined in `/etc/nixos/configuration.nix` {#environment-defined-in-etcnixosconfiguration.nix}
320
321For the sake of completeness, here's how to install the environment system-wide
322on NixOS.
323
324```nix
325{ # ...
326
327 environment.systemPackages = with pkgs; [
328 (python310.withPackages(ps: with ps; [ numpy toolz ]))
329 ];
330}
331```
332
333### Developing with Python {#developing-with-python}
334
335Above, we were mostly just focused on use cases and what to do to get started
336creating working Python environments in nix.
337
338Now that you know the basics to be up and running, it is time to take a step
339back and take a deeper look at how Python packages are packaged on Nix. Then,
340we will look at how you can use development mode with your code.
341
342#### Python library packages in Nixpkgs {#python-library-packages-in-nixpkgs}
343
344With Nix all packages are built by functions. The main function in Nix for
345building Python libraries is `buildPythonPackage`. Let's see how we can build the
346`toolz` package.
347
348```nix
349{ lib
350, buildPythonPackage
351, fetchPypi
352}:
353
354buildPythonPackage rec {
355 pname = "toolz";
356 version = "0.10.0";
357 format = "setuptools";
358
359 src = fetchPypi {
360 inherit pname version;
361 hash = "sha256-CP3V73yWSArRHBLUct4hrNMjWZlvaaUlkpm1QP66RWA=";
362 };
363
364 # has no tests
365 doCheck = false;
366
367 pythonImportsCheck = [
368 "toolz.itertoolz"
369 "toolz.functoolz"
370 "toolz.dicttoolz"
371 ];
372
373 meta = with lib; {
374 changelog = "https://github.com/pytoolz/toolz/releases/tag/${version}";
375 homepage = "https://github.com/pytoolz/toolz";
376 description = "List processing tools and functional utilities";
377 license = licenses.bsd3;
378 maintainers = with maintainers; [ fridh ];
379 };
380}
381```
382
383What happens here? The function `buildPythonPackage` is called and as argument
384it accepts a set. In this case the set is a recursive set, `rec`. One of the
385arguments is the name of the package, which consists of a basename (generally
386following the name on PyPi) and a version. Another argument, `src` specifies the
387source, which in this case is fetched from PyPI using the helper function
388`fetchPypi`. The argument `doCheck` is used to set whether tests should be run
389when building the package. Since there are no tests, we rely on `pythonImportsCheck`
390to test whether the package can be imported. Furthermore, we specify some meta
391information. The output of the function is a derivation.
392
393An expression for `toolz` can be found in the Nixpkgs repository. As explained
394in the introduction of this Python section, a derivation of `toolz` is available
395for each interpreter version, e.g. `python311.pkgs.toolz` refers to the `toolz`
396derivation corresponding to the CPython 3.11 interpreter.
397
398The above example works when you're directly working on
399`pkgs/top-level/python-packages.nix` in the Nixpkgs repository. Often though,
400you will want to test a Nix expression outside of the Nixpkgs tree.
401
402The following expression creates a derivation for the `toolz` package,
403and adds it along with a `numpy` package to a Python environment.
404
405```nix
406with import <nixpkgs> {};
407
408( let
409 my_toolz = python311.pkgs.buildPythonPackage rec {
410 pname = "toolz";
411 version = "0.10.0";
412 format = "setuptools";
413
414 src = fetchPypi {
415 inherit pname version;
416 hash = "sha256-CP3V73yWSArRHBLUct4hrNMjWZlvaaUlkpm1QP66RWA=";
417 };
418
419 # has no tests
420 doCheck = false;
421
422 meta = {
423 homepage = "https://github.com/pytoolz/toolz/";
424 description = "List processing tools and functional utilities";
425 # [...]
426 };
427 };
428
429 in python311.withPackages (ps: with ps; [
430 numpy
431 my_toolz
432 ])
433).env
434```
435
436Executing `nix-shell` will result in an environment in which you can use
437Python 3.11 and the `toolz` package. As you can see we had to explicitly mention
438for which Python version we want to build a package.
439
440So, what did we do here? Well, we took the Nix expression that we used earlier
441to build a Python environment, and said that we wanted to include our own
442version of `toolz`, named `my_toolz`. To introduce our own package in the scope
443of `withPackages` we used a `let` expression. You can see that we used
444`ps.numpy` to select numpy from the nixpkgs package set (`ps`). We did not take
445`toolz` from the Nixpkgs package set this time, but instead took our own version
446that we introduced with the `let` expression.
447
448#### Handling dependencies {#handling-dependencies}
449
450Our example, `toolz`, does not have any dependencies on other Python packages or
451system libraries. According to the manual, `buildPythonPackage` uses the
452arguments `buildInputs` and `propagatedBuildInputs` to specify dependencies. If
453something is exclusively a build-time dependency, then the dependency should be
454included in `buildInputs`, but if it is (also) a runtime dependency, then it
455should be added to `propagatedBuildInputs`. Test dependencies are considered
456build-time dependencies and passed to `nativeCheckInputs`.
457
458The following example shows which arguments are given to `buildPythonPackage` in
459order to build [`datashape`](https://github.com/blaze/datashape).
460
461```nix
462{ lib
463, buildPythonPackage
464, fetchPypi
465
466# dependencies
467, numpy, multipledispatch, python-dateutil
468
469# tests
470, pytest
471}:
472
473buildPythonPackage rec {
474 pname = "datashape";
475 version = "0.4.7";
476 format = "setuptools";
477
478 src = fetchPypi {
479 inherit pname version;
480 hash = "sha256-FLLvdm1MllKrgTGC6Gb0k0deZeVYvtCCLji/B7uhong=";
481 };
482
483 propagatedBuildInputs = [
484 multipledispatch
485 numpy
486 python-dateutil
487 ];
488
489 nativeCheckInputs = [
490 pytest
491 ];
492
493 meta = with lib; {
494 changelog = "https://github.com/blaze/datashape/releases/tag/${version}";
495 homepage = "https://github.com/ContinuumIO/datashape";
496 description = "A data description language";
497 license = licenses.bsd2;
498 maintainers = with maintainers; [ fridh ];
499 };
500}
501```
502
503We can see several runtime dependencies, `numpy`, `multipledispatch`, and
504`python-dateutil`. Furthermore, we have `nativeCheckInputs` with `pytest`.
505`pytest` is a test runner and is only used during the `checkPhase` and is
506therefore not added to `propagatedBuildInputs`.
507
508In the previous case we had only dependencies on other Python packages to consider.
509Occasionally you have also system libraries to consider. E.g., `lxml` provides
510Python bindings to `libxml2` and `libxslt`. These libraries are only required
511when building the bindings and are therefore added as `buildInputs`.
512
513```nix
514{ lib
515, pkgs
516, buildPythonPackage
517, fetchPypi
518}:
519
520buildPythonPackage rec {
521 pname = "lxml";
522 version = "3.4.4";
523 format = "setuptools";
524
525 src = fetchPypi {
526 inherit pname version;
527 hash = "sha256-s9NiusRxFydHzaNRMjjxFcvWxfi45jGb9ql6eJJyQJk=";
528 };
529
530 buildInputs = [
531 pkgs.libxml2
532 pkgs.libxslt
533 ];
534
535 meta = with lib; {
536 changelog = "https://github.com/lxml/lxml/releases/tag/lxml-${version}";
537 description = "Pythonic binding for the libxml2 and libxslt libraries";
538 homepage = "https://lxml.de";
539 license = licenses.bsd3;
540 maintainers = with maintainers; [ sjourdois ];
541 };
542}
543```
544
545In this example `lxml` and Nix are able to work out exactly where the relevant
546files of the dependencies are. This is not always the case.
547
548The example below shows bindings to The Fastest Fourier Transform in the West,
549commonly known as FFTW. On Nix we have separate packages of FFTW for the
550different types of floats (`"single"`, `"double"`, `"long-double"`). The
551bindings need all three types, and therefore we add all three as `buildInputs`.
552The bindings don't expect to find each of them in a different folder, and
553therefore we have to set `LDFLAGS` and `CFLAGS`.
554
555```nix
556{ lib
557, pkgs
558, buildPythonPackage
559, fetchPypi
560
561# dependencies
562, numpy
563, scipy
564}:
565
566buildPythonPackage rec {
567 pname = "pyFFTW";
568 version = "0.9.2";
569 format = "setuptools";
570
571 src = fetchPypi {
572 inherit pname version;
573 hash = "sha256-9ru2r6kwhUCaskiFoaPNuJCfCVoUL01J40byvRt4kHQ=";
574 };
575
576 buildInputs = [
577 pkgs.fftw
578 pkgs.fftwFloat
579 pkgs.fftwLongDouble
580 ];
581
582 propagatedBuildInputs = [
583 numpy
584 scipy
585 ];
586
587 preConfigure = ''
588 export LDFLAGS="-L${pkgs.fftw.dev}/lib -L${pkgs.fftwFloat.out}/lib -L${pkgs.fftwLongDouble.out}/lib"
589 export CFLAGS="-I${pkgs.fftw.dev}/include -I${pkgs.fftwFloat.dev}/include -I${pkgs.fftwLongDouble.dev}/include"
590 '';
591
592 # Tests cannot import pyfftw. pyfftw works fine though.
593 doCheck = false;
594
595 meta = with lib; {
596 changelog = "https://github.com/pyFFTW/pyFFTW/releases/tag/v${version}";
597 description = "A pythonic wrapper around FFTW, the FFT library, presenting a unified interface for all the supported transforms";
598 homepage = "http://hgomersall.github.com/pyFFTW";
599 license = with licenses; [ bsd2 bsd3 ];
600 maintainers = with maintainers; [ fridh ];
601 };
602}
603```
604
605Note also the line `doCheck = false;`, we explicitly disabled running the test-suite.
606
607#### Testing Python Packages {#testing-python-packages}
608
609It is highly encouraged to have testing as part of the package build. This
610helps to avoid situations where the package was able to build and install,
611but is not usable at runtime. Currently, all packages will use the `test`
612command provided by the setup.py (i.e. `python setup.py test`). However,
613this is currently deprecated https://github.com/pypa/setuptools/pull/1878
614and your package should provide its own checkPhase.
615
616*NOTE:* The `checkPhase` for python maps to the `installCheckPhase` on a
617normal derivation. This is due to many python packages not behaving well
618to the pre-installed version of the package. Version info, and natively
619compiled extensions generally only exist in the install directory, and
620thus can cause issues when a test suite asserts on that behavior.
621
622*NOTE:* Tests should only be disabled if they don't agree with nix
623(e.g. external dependencies, network access, flakey tests), however,
624as many tests should be enabled as possible. Failing tests can still be
625a good indication that the package is not in a valid state.
626
627#### Using pytest {#using-pytest}
628
629Pytest is the most common test runner for python repositories. A trivial
630test run would be:
631
632```
633 nativeCheckInputs = [ pytest ];
634 checkPhase = ''
635 runHook preCheck
636
637 pytest
638
639 runHook postCheck
640 '';
641```
642
643However, many repositories' test suites do not translate well to nix's build
644sandbox, and will generally need many tests to be disabled.
645
646To filter tests using pytest, one can do the following:
647
648```
649 nativeCheckInputs = [ pytest ];
650 # avoid tests which need additional data or touch network
651 checkPhase = ''
652 runHook preCheck
653
654 pytest tests/ --ignore=tests/integration -k 'not download and not update' --ignore=tests/test_failing.py
655
656 runHook postCheck
657 '';
658```
659
660`--ignore` will tell pytest to ignore that file or directory from being
661collected as part of a test run. This is useful is a file uses a package
662which is not available in nixpkgs, thus skipping that test file is much
663easier than having to create a new package.
664
665`-k` is used to define a predicate for test names. In this example, we are
666filtering out tests which contain `download` or `update` in their test case name.
667Only one `-k` argument is allowed, and thus a long predicate should be concatenated
668with “\\” and wrapped to the next line.
669
670*NOTE:* In pytest==6.0.1, the use of “\\” to continue a line (e.g. `-k 'not download \'`) has
671been removed, in this case, it's recommended to use `pytestCheckHook`.
672
673#### Using pytestCheckHook {#using-pytestcheckhook}
674
675`pytestCheckHook` is a convenient hook which will substitute the setuptools
676`test` command for a `checkPhase` which runs `pytest`. This is also beneficial
677when a package may need many items disabled to run the test suite.
678
679Using the example above, the analogous `pytestCheckHook` usage would be:
680
681```
682 nativeCheckInputs = [
683 pytestCheckHook
684 ];
685
686 # requires additional data
687 pytestFlagsArray = [
688 "tests/"
689 "--ignore=tests/integration"
690 ];
691
692 disabledTests = [
693 # touches network
694 "download"
695 "update"
696 ];
697
698 disabledTestPaths = [
699 "tests/test_failing.py"
700 ];
701```
702
703This is especially useful when tests need to be conditionally disabled,
704for example:
705
706```
707 disabledTests = [
708 # touches network
709 "download"
710 "update"
711 ] ++ lib.optionals (pythonAtLeast "3.8") [
712 # broken due to python3.8 async changes
713 "async"
714 ] ++ lib.optionals stdenv.isDarwin [
715 # can fail when building with other packages
716 "socket"
717 ];
718```
719
720Trying to concatenate the related strings to disable tests in a regular
721`checkPhase` would be much harder to read. This also enables us to comment on
722why specific tests are disabled.
723
724#### Using pythonImportsCheck {#using-pythonimportscheck}
725
726Although unit tests are highly preferred to validate correctness of a package, not
727all packages have test suites that can be run easily, and some have none at all.
728To help ensure the package still works, `pythonImportsCheck` can attempt to import
729the listed modules.
730
731```
732 pythonImportsCheck = [
733 "requests"
734 "urllib"
735 ];
736```
737
738roughly translates to:
739
740```
741 postCheck = ''
742 PYTHONPATH=$out/${python.sitePackages}:$PYTHONPATH
743 python -c "import requests; import urllib"
744 '';
745```
746
747However, this is done in its own phase, and not dependent on whether `doCheck = true;`.
748
749This can also be useful in verifying that the package doesn't assume commonly
750present packages (e.g. `setuptools`).
751
752#### Using pythonRelaxDepsHook {#using-pythonrelaxdepshook}
753
754It is common for upstream to specify a range of versions for its package
755dependencies. This makes sense, since it ensures that the package will be built
756with a subset of packages that is well tested. However, this commonly causes
757issues when packaging in Nixpkgs, because the dependencies that this package
758may need are too new or old for the package to build correctly. We also cannot
759package multiple versions of the same package since this may cause conflicts
760in `PYTHONPATH`.
761
762One way to side step this issue is to relax the dependencies. This can be done
763by either removing the package version range or by removing the package
764declaration entirely. This can be done using the `pythonRelaxDepsHook` hook. For
765example, given the following `requirements.txt` file:
766
767```
768pkg1<1.0
769pkg2
770pkg3>=1.0,<=2.0
771```
772
773we can do:
774
775```
776 nativeBuildInputs = [
777 pythonRelaxDepsHook
778 ];
779 pythonRelaxDeps = [
780 "pkg1"
781 "pkg3"
782 ];
783 pythonRemoveDeps = [
784 "pkg2"
785 ];
786```
787
788which would result in the following `requirements.txt` file:
789
790```
791pkg1
792pkg3
793```
794
795Another option is to pass `true`, that will relax/remove all dependencies, for
796example:
797
798```
799 nativeBuildInputs = [ pythonRelaxDepsHook ];
800 pythonRelaxDeps = true;
801```
802
803which would result in the following `requirements.txt` file:
804
805```
806pkg1
807pkg2
808pkg3
809```
810
811In general you should always use `pythonRelaxDeps`, because `pythonRemoveDeps`
812will convert build errors into runtime errors. However `pythonRemoveDeps` may
813still be useful in exceptional cases, and also to remove dependencies wrongly
814declared by upstream (for example, declaring `black` as a runtime dependency
815instead of a dev dependency).
816
817Keep in mind that while the examples above are done with `requirements.txt`,
818`pythonRelaxDepsHook` works by modifying the resulting wheel file, so it should
819work in any of the formats supported by `buildPythonPackage` currently,
820with the exception of `other` (see `format` in
821[`buildPythonPackage` parameters](#buildpythonpackage-parameters) for more details).
822
823#### Using unittestCheckHook {#using-unittestcheckhook}
824
825`unittestCheckHook` is a hook which will substitute the setuptools `test` command for a `checkPhase` which runs `python -m unittest discover`:
826
827```
828 nativeCheckInputs = [
829 unittestCheckHook
830 ];
831
832 unittestFlagsArray = [
833 "-s" "tests" "-v"
834 ];
835```
836
837#### Using sphinxHook {#using-sphinxhook}
838
839The `sphinxHook` is a helpful tool to build documentation and manpages
840using the popular Sphinx documentation generator.
841It is setup to automatically find common documentation source paths and
842render them using the default `html` style.
843
844```
845 outputs = [
846 "out"
847 "doc"
848 ];
849
850 nativeBuildInputs = [
851 sphinxHook
852 ];
853```
854
855The hook will automatically build and install the artifact into the
856`doc` output, if it exists. It also provides an automatic diversion
857for the artifacts of the `man` builder into the `man` target.
858
859```
860 outputs = [
861 "out"
862 "doc"
863 "man"
864 ];
865
866 # Use multiple builders
867 sphinxBuilders = [
868 "singlehtml"
869 "man"
870 ];
871```
872
873Overwrite `sphinxRoot` when the hook is unable to find your
874documentation source root.
875
876```
877 # Configure sphinxRoot for uncommon paths
878 sphinxRoot = "weird/docs/path";
879```
880
881The hook is also available to packages outside the python ecosystem by
882referencing it using `sphinxHook` from top-level.
883
884### Develop local package {#develop-local-package}
885
886As a Python developer you're likely aware of [development mode](http://setuptools.readthedocs.io/en/latest/setuptools.html#development-mode)
887(`python setup.py develop`); instead of installing the package this command
888creates a special link to the project code. That way, you can run updated code
889without having to reinstall after each and every change you make. Development
890mode is also available. Let's see how you can use it.
891
892In the previous Nix expression the source was fetched from a url. We can also
893refer to a local source instead using `src = ./path/to/source/tree;`
894
895If we create a `shell.nix` file which calls `buildPythonPackage`, and if `src`
896is a local source, and if the local source has a `setup.py`, then development
897mode is activated.
898
899In the following example, we create a simple environment that has a Python 3.11
900version of our package in it, as well as its dependencies and other packages we
901like to have in the environment, all specified with `propagatedBuildInputs`.
902Indeed, we can just add any package we like to have in our environment to
903`propagatedBuildInputs`.
904
905```nix
906with import <nixpkgs> {};
907with python311Packages;
908
909buildPythonPackage rec {
910 name = "mypackage";
911 src = ./path/to/package/source;
912 propagatedBuildInputs = [
913 pytest
914 numpy
915 pkgs.libsndfile
916 ];
917}
918```
919
920It is important to note that due to how development mode is implemented on Nix
921it is not possible to have multiple packages simultaneously in development mode.
922
923### Organising your packages {#organising-your-packages}
924
925So far we discussed how you can use Python on Nix, and how you can develop with
926it. We've looked at how you write expressions to package Python packages, and we
927looked at how you can create environments in which specified packages are
928available.
929
930At some point you'll likely have multiple packages which you would
931like to be able to use in different projects. In order to minimise unnecessary
932duplication we now look at how you can maintain a repository with your
933own packages. The important functions here are `import` and `callPackage`.
934
935### Including a derivation using `callPackage` {#including-a-derivation-using-callpackage}
936
937Earlier we created a Python environment using `withPackages`, and included the
938`toolz` package via a `let` expression.
939Let's split the package definition from the environment definition.
940
941We first create a function that builds `toolz` in `~/path/to/toolz/release.nix`
942
943```nix
944{ lib
945, buildPythonPackage
946}:
947
948buildPythonPackage rec {
949 pname = "toolz";
950 version = "0.10.0";
951 format = "setuptools";
952
953 src = fetchPypi {
954 inherit pname version;
955 hash = "sha256-CP3V73yWSArRHBLUct4hrNMjWZlvaaUlkpm1QP66RWA=";
956 };
957
958 meta = with lib; {
959 changelog = "https://github.com/pytoolz/toolz/releases/tag/${version}";
960 homepage = "https://github.com/pytoolz/toolz/";
961 description = "List processing tools and functional utilities";
962 license = licenses.bsd3;
963 maintainers = with maintainers; [ fridh ];
964 };
965}
966```
967
968It takes an argument `buildPythonPackage`. We now call this function using
969`callPackage` in the definition of our environment
970
971```nix
972with import <nixpkgs> {};
973
974( let
975 toolz = callPackage /path/to/toolz/release.nix {
976 buildPythonPackage = python310
977Packages.buildPythonPackage;
978 };
979 in python310.withPackages (ps: [
980 ps.numpy
981 toolz
982 ])
983).env
984```
985
986Important to remember is that the Python version for which the package is made
987depends on the `python` derivation that is passed to `buildPythonPackage`. Nix
988tries to automatically pass arguments when possible, which is why generally you
989don't explicitly define which `python` derivation should be used. In the above
990example we use `buildPythonPackage` that is part of the set `python3Packages`,
991and in this case the `python3` interpreter is automatically used.
992
993## Reference {#reference}
994
995### Interpreters {#interpreters}
996
997Versions 2.7, 3.8, 3.9, 3.10 and 3.11 of the CPython interpreter are available
998as respectively `python27`, python38`, `python39`, `python310` and `python311`.
999The aliases `python2` and `python3` correspond to respectively `python27` and
1000`python310`. The attribute `python` maps to `python2`. The PyPy interpreters
1001compatible with Python 2.7 and 3 are available as `pypy27` and `pypy3`, with
1002aliases `pypy2` mapping to `pypy27` and `pypy` mapping to `pypy2`. The Nix
1003expressions for the interpreters can be found in
1004`pkgs/development/interpreters/python`.
1005
1006All packages depending on any Python interpreter get appended
1007`out/{python.sitePackages}` to `$PYTHONPATH` if such directory
1008exists.
1009
1010#### Missing `tkinter` module standard library {#missing-tkinter-module-standard-library}
1011
1012To reduce closure size the `Tkinter`/`tkinter` is available as a separate package, `pythonPackages.tkinter`.
1013
1014#### Attributes on interpreters packages {#attributes-on-interpreters-packages}
1015
1016Each interpreter has the following attributes:
1017
1018- `libPrefix`. Name of the folder in `${python}/lib/` for corresponding interpreter.
1019- `interpreter`. Alias for `${python}/bin/${executable}`.
1020- `buildEnv`. Function to build python interpreter environments with extra packages bundled together. See section *python.buildEnv function* for usage and documentation.
1021- `withPackages`. Simpler interface to `buildEnv`. See section *python.withPackages function* for usage and documentation.
1022- `sitePackages`. Alias for `lib/${libPrefix}/site-packages`.
1023- `executable`. Name of the interpreter executable, e.g. `python3.10`.
1024- `pkgs`. Set of Python packages for that specific interpreter. The package set can be modified by overriding the interpreter and passing `packageOverrides`.
1025
1026### Optimizations {#optimizations}
1027
1028The Python interpreters are by default not built with optimizations enabled, because
1029the builds are in that case not reproducible. To enable optimizations, override the
1030interpreter of interest, e.g using
1031
1032```
1033let
1034 pkgs = import ./. {};
1035 mypython = pkgs.python3.override {
1036 enableOptimizations = true;
1037 reproducibleBuild = false;
1038 self = mypython;
1039 };
1040in mypython
1041```
1042
1043### Building packages and applications {#building-packages-and-applications}
1044
1045Python libraries and applications that use `setuptools` or
1046`distutils` are typically built with respectively the `buildPythonPackage` and
1047`buildPythonApplication` functions. These two functions also support installing a `wheel`.
1048
1049All Python packages reside in `pkgs/top-level/python-packages.nix` and all
1050applications elsewhere. In case a package is used as both a library and an
1051application, then the package should be in `pkgs/top-level/python-packages.nix`
1052since only those packages are made available for all interpreter versions. The
1053preferred location for library expressions is in
1054`pkgs/development/python-modules`. It is important that these packages are
1055called from `pkgs/top-level/python-packages.nix` and not elsewhere, to guarantee
1056the right version of the package is built.
1057
1058Based on the packages defined in `pkgs/top-level/python-packages.nix` an
1059attribute set is created for each available Python interpreter. The available
1060sets are
1061
1062* `pkgs.python27Packages`
1063* `pkgs.python3Packages`
1064* `pkgs.python38Packages`
1065* `pkgs.python39Packages`
1066* `pkgs.python310Packages`
1067* `pkgs.python311Packages`
1068* `pkgs.pypyPackages`
1069
1070and the aliases
1071
1072* `pkgs.python2Packages` pointing to `pkgs.python27Packages`
1073* `pkgs.python3Packages` pointing to `pkgs.python310Packages`
1074* `pkgs.pythonPackages` pointing to `pkgs.python2Packages`
1075
1076#### `buildPythonPackage` function {#buildpythonpackage-function}
1077
1078The `buildPythonPackage` function is implemented in
1079`pkgs/development/interpreters/python/mk-python-derivation.nix`
1080using setup hooks.
1081
1082The following is an example:
1083
1084```nix
1085{ lib
1086, buildPythonPackage
1087, fetchPypi
1088
1089# build-system
1090, setuptools-scm
1091
1092# dependencies
1093, attrs
1094, pluggy
1095, py
1096, setuptools
1097, six
1098
1099# tests
1100, hypothesis
1101 }:
1102
1103buildPythonPackage rec {
1104 pname = "pytest";
1105 version = "3.3.1";
1106 format = "setuptools";
1107
1108 src = fetchPypi {
1109 inherit pname version;
1110 hash = "sha256-z4Q23FnYaVNG/NOrKW3kZCXsqwDWQJbOvnn7Ueyy65M=";
1111 };
1112
1113 postPatch = ''
1114 # don't test bash builtins
1115 rm testing/test_argcomplete.py
1116 '';
1117
1118 nativeBuildInputs = [
1119 setuptools-scm
1120 ];
1121
1122 propagatedBuildInputs = [
1123 attrs
1124 py
1125 setuptools
1126 six
1127 pluggy
1128 ];
1129
1130 nativeCheckInputs = [
1131 hypothesis
1132 ];
1133
1134 meta = with lib; {
1135 changelog = "https://github.com/pytest-dev/pytest/releases/tag/${version}";
1136 description = "Framework for writing tests";
1137 homepage = "https://github.com/pytest-dev/pytest";
1138 license = licenses.mit;
1139 maintainers = with maintainers; [ domenkozar lovek323 madjar lsix ];
1140 };
1141}
1142```
1143
1144The `buildPythonPackage` mainly does four things:
1145
1146* In the `buildPhase`, it calls `${python.pythonForBuild.interpreter} setup.py bdist_wheel` to
1147 build a wheel binary zipfile.
1148* In the `installPhase`, it installs the wheel file using `pip install *.whl`.
1149* In the `postFixup` phase, the `wrapPythonPrograms` bash function is called to
1150 wrap all programs in the `$out/bin/*` directory to include `$PATH`
1151 environment variable and add dependent libraries to script's `sys.path`.
1152* In the `installCheck` phase, `${python.interpreter} setup.py test` is run.
1153
1154By default tests are run because `doCheck = true`. Test dependencies, like
1155e.g. the test runner, should be added to `nativeCheckInputs`.
1156
1157By default `meta.platforms` is set to the same value
1158as the interpreter unless overridden otherwise.
1159
1160##### `buildPythonPackage` parameters {#buildpythonpackage-parameters}
1161
1162All parameters from `stdenv.mkDerivation` function are still supported. The
1163following are specific to `buildPythonPackage`:
1164
1165* `catchConflicts ? true`: If `true`, abort package build if a package name
1166 appears more than once in dependency tree. Default is `true`.
1167* `disabled ? false`: If `true`, package is not built for the particular Python
1168 interpreter version.
1169* `dontWrapPythonPrograms ? false`: Skip wrapping of Python programs.
1170* `permitUserSite ? false`: Skip setting the `PYTHONNOUSERSITE` environment
1171 variable in wrapped programs.
1172* `format ? "setuptools"`: Format of the source. Valid options are
1173 `"setuptools"`, `"pyproject"`, `"flit"`, `"wheel"`, and `"other"`.
1174 `"setuptools"` is for when the source has a `setup.py` and `setuptools` is
1175 used to build a wheel, `flit`, in case `flit` should be used to build a wheel,
1176 and `wheel` in case a wheel is provided. Use `other` when a custom
1177 `buildPhase` and/or `installPhase` is needed.
1178* `makeWrapperArgs ? []`: A list of strings. Arguments to be passed to
1179 `makeWrapper`, which wraps generated binaries. By default, the arguments to
1180 `makeWrapper` set `PATH` and `PYTHONPATH` environment variables before calling
1181 the binary. Additional arguments here can allow a developer to set environment
1182 variables which will be available when the binary is run. For example,
1183 `makeWrapperArgs = ["--set FOO BAR" "--set BAZ QUX"]`.
1184* `namePrefix`: Prepends text to `${name}` parameter. In case of libraries, this
1185 defaults to `"python3.8-"` for Python 3.8, etc., and in case of applications
1186 to `""`.
1187* `pipInstallFlags ? []`: A list of strings. Arguments to be passed to `pip
1188 install`. To pass options to `python setup.py install`, use
1189 `--install-option`. E.g., `pipInstallFlags=["--install-option='--cpp_implementation'"]`.
1190* `pythonPath ? []`: List of packages to be added into `$PYTHONPATH`. Packages
1191 in `pythonPath` are not propagated (contrary to `propagatedBuildInputs`).
1192* `preShellHook`: Hook to execute commands before `shellHook`.
1193* `postShellHook`: Hook to execute commands after `shellHook`.
1194* `removeBinByteCode ? true`: Remove bytecode from `/bin`. Bytecode is only
1195 created when the filenames end with `.py`.
1196* `setupPyGlobalFlags ? []`: List of flags passed to `setup.py` command.
1197* `setupPyBuildFlags ? []`: List of flags passed to `setup.py build_ext` command.
1198
1199The `stdenv.mkDerivation` function accepts various parameters for describing
1200build inputs (see "Specifying dependencies"). The following are of special
1201interest for Python packages, either because these are primarily used, or
1202because their behaviour is different:
1203
1204* `nativeBuildInputs ? []`: Build-time only dependencies. Typically executables
1205 as well as the items listed in `setup_requires`.
1206* `buildInputs ? []`: Build and/or run-time dependencies that need to be
1207 compiled for the host machine. Typically non-Python libraries which are being
1208 linked.
1209* `nativeCheckInputs ? []`: Dependencies needed for running the `checkPhase`. These
1210 are added to `nativeBuildInputs` when `doCheck = true`. Items listed in
1211 `tests_require` go here.
1212* `propagatedBuildInputs ? []`: Aside from propagating dependencies,
1213 `buildPythonPackage` also injects code into and wraps executables with the
1214 paths included in this list. Items listed in `install_requires` go here.
1215
1216##### Overriding Python packages {#overriding-python-packages}
1217
1218The `buildPythonPackage` function has a `overridePythonAttrs` method that can be
1219used to override the package. In the following example we create an environment
1220where we have the `blaze` package using an older version of `pandas`. We
1221override first the Python interpreter and pass `packageOverrides` which contains
1222the overrides for packages in the package set.
1223
1224```nix
1225with import <nixpkgs> {};
1226
1227(let
1228 python = let
1229 packageOverrides = self: super: {
1230 pandas = super.pandas.overridePythonAttrs(old: rec {
1231 version = "0.19.1";
1232 src = fetchPypi {
1233 pname = "pandas";
1234 inherit version;
1235 hash = "sha256-JQn+rtpy/OA2deLszSKEuxyttqBzcAil50H+JDHUdCE=";
1236 };
1237 });
1238 };
1239 in pkgs.python3.override {inherit packageOverrides; self = python;};
1240
1241in python.withPackages(ps: [ ps.blaze ])).env
1242```
1243
1244#### Optional extra dependencies {#python-optional-dependencies}
1245
1246Some packages define optional dependencies for additional features. With
1247`setuptools` this is called `extras_require` and `flit` calls it
1248`extras-require`, while PEP 621 calls these `optional-dependencies`. A
1249method for supporting this is by declaring the extras of a package in its
1250`passthru`, e.g. in case of the package `dask`
1251
1252```nix
1253passthru.optional-dependencies = {
1254 complete = [ distributed ];
1255};
1256```
1257
1258and letting the package requiring the extra add the list to its dependencies
1259
1260```nix
1261propagatedBuildInputs = [
1262 ...
1263] ++ dask.optional-dependencies.complete;
1264```
1265
1266Note this method is preferred over adding parameters to builders, as that can
1267result in packages depending on different variants and thereby causing
1268collisions.
1269
1270#### `buildPythonApplication` function {#buildpythonapplication-function}
1271
1272The `buildPythonApplication` function is practically the same as
1273`buildPythonPackage`. The main purpose of this function is to build a Python
1274package where one is interested only in the executables, and not importable
1275modules. For that reason, when adding this package to a `python.buildEnv`, the
1276modules won't be made available.
1277
1278Another difference is that `buildPythonPackage` by default prefixes the names of
1279the packages with the version of the interpreter. Because this is irrelevant for
1280applications, the prefix is omitted.
1281
1282When packaging a Python application with `buildPythonApplication`, it should be
1283called with `callPackage` and passed `python` or `pythonPackages` (possibly
1284specifying an interpreter version), like this:
1285
1286```nix
1287{ lib
1288, python3
1289, fetchPypi
1290}:
1291
1292python3.pkgs.buildPythonApplication rec {
1293 pname = "luigi";
1294 version = "2.7.9";
1295 format = "setuptools";
1296
1297 src = fetchPypi {
1298 inherit pname version;
1299 hash = "sha256-Pe229rT0aHwA98s+nTHQMEFKZPo/yw6sot8MivFDvAw=";
1300 };
1301
1302 propagatedBuildInputs = with python3.pkgs; [
1303 tornado
1304 python-daemon
1305 ];
1306
1307 meta = with lib; {
1308 ...
1309 };
1310}
1311```
1312
1313This is then added to `all-packages.nix` just as any other application would be.
1314
1315```nix
1316luigi = callPackage ../applications/networking/cluster/luigi { };
1317```
1318
1319Since the package is an application, a consumer doesn't need to care about
1320Python versions or modules, which is why they don't go in `pythonPackages`.
1321
1322#### `toPythonApplication` function {#topythonapplication-function}
1323
1324A distinction is made between applications and libraries, however, sometimes a
1325package is used as both. In this case the package is added as a library to
1326`python-packages.nix` and as an application to `all-packages.nix`. To reduce
1327duplication the `toPythonApplication` can be used to convert a library to an
1328application.
1329
1330The Nix expression shall use `buildPythonPackage` and be called from
1331`python-packages.nix`. A reference shall be created from `all-packages.nix` to
1332the attribute in `python-packages.nix`, and the `toPythonApplication` shall be
1333applied to the reference:
1334
1335```nix
1336youtube-dl = with pythonPackages; toPythonApplication youtube-dl;
1337```
1338
1339#### `toPythonModule` function {#topythonmodule-function}
1340
1341In some cases, such as bindings, a package is created using
1342`stdenv.mkDerivation` and added as attribute in `all-packages.nix`. The Python
1343bindings should be made available from `python-packages.nix`. The
1344`toPythonModule` function takes a derivation and makes certain Python-specific
1345modifications.
1346
1347```nix
1348opencv = toPythonModule (pkgs.opencv.override {
1349 enablePython = true;
1350 pythonPackages = self;
1351});
1352```
1353
1354Do pay attention to passing in the right Python version!
1355
1356#### `python.buildEnv` function {#python.buildenv-function}
1357
1358Python environments can be created using the low-level `pkgs.buildEnv` function.
1359This example shows how to create an environment that has the Pyramid Web Framework.
1360Saving the following as `default.nix`
1361
1362```nix
1363with import <nixpkgs> {};
1364
1365python.buildEnv.override {
1366 extraLibs = [ pythonPackages.pyramid ];
1367 ignoreCollisions = true;
1368}
1369```
1370
1371and running `nix-build` will create
1372
1373```
1374/nix/store/cf1xhjwzmdki7fasgr4kz6di72ykicl5-python-2.7.8-env
1375```
1376
1377with wrapped binaries in `bin/`.
1378
1379You can also use the `env` attribute to create local environments with needed
1380packages installed. This is somewhat comparable to `virtualenv`. For example,
1381running `nix-shell` with the following `shell.nix`
1382
1383```nix
1384with import <nixpkgs> {};
1385
1386(python3.buildEnv.override {
1387 extraLibs = with python3Packages; [
1388 numpy
1389 requests
1390 ];
1391}).env
1392```
1393
1394will drop you into a shell where Python will have the
1395specified packages in its path.
1396
1397##### `python.buildEnv` arguments {#python.buildenv-arguments}
1398
1399
1400* `extraLibs`: List of packages installed inside the environment.
1401* `postBuild`: Shell command executed after the build of environment.
1402* `ignoreCollisions`: Ignore file collisions inside the environment (default is `false`).
1403* `permitUserSite`: Skip setting the `PYTHONNOUSERSITE` environment variable in
1404 wrapped binaries in the environment.
1405
1406#### `python.withPackages` function {#python.withpackages-function}
1407
1408The `python.withPackages` function provides a simpler interface to the `python.buildEnv` functionality.
1409It takes a function as an argument that is passed the set of python packages and returns the list
1410of the packages to be included in the environment. Using the `withPackages` function, the previous
1411example for the Pyramid Web Framework environment can be written like this:
1412
1413```nix
1414with import <nixpkgs> {};
1415
1416python.withPackages (ps: [ ps.pyramid ])
1417```
1418
1419`withPackages` passes the correct package set for the specific interpreter
1420version as an argument to the function. In the above example, `ps` equals
1421`pythonPackages`. But you can also easily switch to using python3:
1422
1423```nix
1424with import <nixpkgs> {};
1425
1426python3.withPackages (ps: [ ps.pyramid ])
1427```
1428
1429Now, `ps` is set to `python3Packages`, matching the version of the interpreter.
1430
1431As `python.withPackages` simply uses `python.buildEnv` under the hood, it also
1432supports the `env` attribute. The `shell.nix` file from the previous section can
1433thus be also written like this:
1434
1435```nix
1436with import <nixpkgs> {};
1437
1438(python3.withPackages (ps: with ps; [
1439 numpy
1440 requests
1441])).env
1442```
1443
1444In contrast to `python.buildEnv`, `python.withPackages` does not support the
1445more advanced options such as `ignoreCollisions = true` or `postBuild`. If you
1446need them, you have to use `python.buildEnv`.
1447
1448Python 2 namespace packages may provide `__init__.py` that collide. In that case
1449`python.buildEnv` should be used with `ignoreCollisions = true`.
1450
1451#### Setup hooks {#setup-hooks}
1452
1453The following are setup hooks specifically for Python packages. Most of these
1454are used in `buildPythonPackage`.
1455
1456- `eggUnpackhook` to move an egg to the correct folder so it can be installed
1457 with the `eggInstallHook`
1458- `eggBuildHook` to skip building for eggs.
1459- `eggInstallHook` to install eggs.
1460- `flitBuildHook` to build a wheel using `flit`.
1461- `pipBuildHook` to build a wheel using `pip` and PEP 517. Note a build system
1462 (e.g. `setuptools` or `flit`) should still be added as `nativeBuildInput`.
1463- `pipInstallHook` to install wheels.
1464- `pytestCheckHook` to run tests with `pytest`. See [example usage](#using-pytestcheckhook).
1465- `pythonCatchConflictsHook` to check whether a Python package is not already existing.
1466- `pythonImportsCheckHook` to check whether importing the listed modules works.
1467- `pythonRelaxDepsHook` will relax Python dependencies restrictions for the package.
1468 See [example usage](#using-pythonrelaxdepshook).
1469- `pythonRemoveBinBytecode` to remove bytecode from the `/bin` folder.
1470- `setuptoolsBuildHook` to build a wheel using `setuptools`.
1471- `setuptoolsCheckHook` to run tests with `python setup.py test`.
1472- `sphinxHook` to build documentation and manpages using Sphinx.
1473- `venvShellHook` to source a Python 3 `venv` at the `venvDir` location. A
1474 `venv` is created if it does not yet exist. `postVenvCreation` can be used to
1475 to run commands only after venv is first created.
1476- `wheelUnpackHook` to move a wheel to the correct folder so it can be installed
1477 with the `pipInstallHook`.
1478- `unittestCheckHook` will run tests with `python -m unittest discover`. See [example usage](#using-unittestcheckhook).
1479
1480### Development mode {#development-mode}
1481
1482Development or editable mode is supported. To develop Python packages
1483`buildPythonPackage` has additional logic inside `shellPhase` to run `pip
1484install -e . --prefix $TMPDIR/`for the package.
1485
1486Warning: `shellPhase` is executed only if `setup.py` exists.
1487
1488Given a `default.nix`:
1489
1490```nix
1491with import <nixpkgs> {};
1492
1493pythonPackages.buildPythonPackage {
1494 name = "myproject";
1495 buildInputs = with pythonPackages; [ pyramid ];
1496
1497 src = ./.;
1498}
1499```
1500
1501Running `nix-shell` with no arguments should give you the environment in which
1502the package would be built with `nix-build`.
1503
1504Shortcut to setup environments with C headers/libraries and Python packages:
1505
1506```shell
1507nix-shell -p pythonPackages.pyramid zlib libjpeg git
1508```
1509
1510Note: There is a boolean value `lib.inNixShell` set to `true` if nix-shell is invoked.
1511
1512### Tools {#tools}
1513
1514Packages inside nixpkgs are written by hand. However many tools exist in
1515community to help save time. No tool is preferred at the moment.
1516
1517- [pypi2nix](https://github.com/nix-community/pypi2nix): Generate Nix
1518 expressions for your Python project. Note that [sharing derivations from
1519 pypi2nix with nixpkgs is possible but not
1520 encouraged](https://github.com/nix-community/pypi2nix/issues/222#issuecomment-443497376).
1521- [nixpkgs-pytools](https://github.com/nix-community/nixpkgs-pytools)
1522- [poetry2nix](https://github.com/nix-community/poetry2nix)
1523
1524### Deterministic builds {#deterministic-builds}
1525
1526The Python interpreters are now built deterministically. Minor modifications had
1527to be made to the interpreters in order to generate deterministic bytecode. This
1528has security implications and is relevant for those using Python in a
1529`nix-shell`.
1530
1531When the environment variable `DETERMINISTIC_BUILD` is set, all bytecode will
1532have timestamp 1. The `buildPythonPackage` function sets `DETERMINISTIC_BUILD=1`
1533and [PYTHONHASHSEED=0](https://docs.python.org/3.11/using/cmdline.html#envvar-PYTHONHASHSEED).
1534Both are also exported in `nix-shell`.
1535
1536### Automatic tests {#automatic-tests}
1537
1538It is recommended to test packages as part of the build process.
1539Source distributions (`sdist`) often include test files, but not always.
1540
1541By default the command `python setup.py test` is run as part of the
1542`checkPhase`, but often it is necessary to pass a custom `checkPhase`. An
1543example of such a situation is when `py.test` is used.
1544
1545#### Common issues {#common-issues}
1546
1547* Non-working tests can often be deselected. By default `buildPythonPackage`
1548 runs `python setup.py test`. which is deprecated. Most Python modules however
1549 do follow the standard test protocol where the pytest runner can be used
1550 instead. `pytest` supports the `-k` and `--ignore` parameters to ignore test
1551 methods or classes as well as whole files. For `pytestCheckHook` these are
1552 conveniently exposed as `disabledTests` and `disabledTestPaths` respectively.
1553
1554 ```nix
1555 buildPythonPackage {
1556 # ...
1557 nativeCheckInputs = [
1558 pytestCheckHook
1559 ];
1560
1561 disabledTests = [
1562 "function_name"
1563 "other_function"
1564 ];
1565
1566 disabledTestPaths = [
1567 "this/file.py"
1568 ];
1569 }
1570 ```
1571
1572* Tests that attempt to access `$HOME` can be fixed by using the following
1573 work-around before running tests (e.g. `preCheck`): `export HOME=$(mktemp -d)`
1574
1575## FAQ {#faq}
1576
1577### How to solve circular dependencies? {#how-to-solve-circular-dependencies}
1578
1579Consider the packages `A` and `B` that depend on each other. When packaging `B`,
1580a solution is to override package `A` not to depend on `B` as an input. The same
1581should also be done when packaging `A`.
1582
1583### How to override a Python package? {#how-to-override-a-python-package}
1584
1585We can override the interpreter and pass `packageOverrides`. In the following
1586example we rename the `pandas` package and build it.
1587
1588```nix
1589with import <nixpkgs> {};
1590
1591(let
1592 python = let
1593 packageOverrides = self: super: {
1594 pandas = super.pandas.overridePythonAttrs(old: {name="foo";});
1595 };
1596 in pkgs.python310.override {
1597 inherit packageOverrides;
1598 };
1599
1600in python.withPackages (ps: [
1601 ps.pandas
1602])).env
1603```
1604
1605Using `nix-build` on this expression will build an environment that contains the
1606package `pandas` but with the new name `foo`.
1607
1608All packages in the package set will use the renamed package. A typical use case
1609is to switch to another version of a certain package. For example, in the
1610Nixpkgs repository we have multiple versions of `django` and `scipy`. In the
1611following example we use a different version of `scipy` and create an
1612environment that uses it. All packages in the Python package set will now use
1613the updated `scipy` version.
1614
1615```nix
1616with import <nixpkgs> {};
1617
1618( let
1619 packageOverrides = self: super: {
1620 scipy = super.scipy_0_17;
1621 };
1622 in (pkgs.python310.override {
1623 inherit packageOverrides;
1624 }).withPackages (ps: [
1625 ps.blaze
1626 ])
1627).env
1628```
1629
1630The requested package `blaze` depends on `pandas` which itself depends on `scipy`.
1631
1632If you want the whole of Nixpkgs to use your modifications, then you can use
1633`overlays` as explained in this manual. In the following example we build a
1634`inkscape` using a different version of `numpy`.
1635
1636```nix
1637let
1638 pkgs = import <nixpkgs> {};
1639 newpkgs = import pkgs.path { overlays = [ (self: super: {
1640 python310 = let
1641 packageOverrides = python-self: python-super: {
1642 numpy = python-super.numpy_1_18;
1643 };
1644 in super.python310.override {inherit packageOverrides;};
1645 } ) ]; };
1646in newpkgs.inkscape
1647```
1648
1649### `python setup.py bdist_wheel` cannot create .whl {#python-setup.py-bdist_wheel-cannot-create-.whl}
1650
1651Executing `python setup.py bdist_wheel` in a `nix-shell`fails with
1652
1653```
1654ValueError: ZIP does not support timestamps before 1980
1655```
1656
1657This is because files from the Nix store (which have a timestamp of the UNIX
1658epoch of January 1, 1970) are included in the .ZIP, but .ZIP archives follow the
1659DOS convention of counting timestamps from 1980.
1660
1661The command `bdist_wheel` reads the `SOURCE_DATE_EPOCH` environment variable,
1662which `nix-shell` sets to 1. Unsetting this variable or giving it a value
1663corresponding to 1980 or later enables building wheels.
1664
1665Use 1980 as timestamp:
1666
1667```shell
1668nix-shell --run "SOURCE_DATE_EPOCH=315532800 python3 setup.py bdist_wheel"
1669```
1670
1671or the current time:
1672
1673```shell
1674nix-shell --run "SOURCE_DATE_EPOCH=$(date +%s) python3 setup.py bdist_wheel"
1675```
1676
1677or unset `SOURCE_DATE_EPOCH`:
1678
1679```shell
1680nix-shell --run "unset SOURCE_DATE_EPOCH; python3 setup.py bdist_wheel"
1681```
1682
1683### `install_data` / `data_files` problems {#install_data-data_files-problems}
1684
1685If you get the following error:
1686
1687```
1688could not create '/nix/store/6l1bvljpy8gazlsw2aw9skwwp4pmvyxw-python-2.7.8/etc':
1689Permission denied
1690```
1691
1692This is a [known bug](https://github.com/pypa/setuptools/issues/130) in
1693`setuptools`. Setuptools `install_data` does not respect `--prefix`. An example
1694of such package using the feature is `pkgs/tools/X11/xpra/default.nix`.
1695
1696As workaround install it as an extra `preInstall` step:
1697
1698```shell
1699${python.pythonForBuild.interpreter} setup.py install_data --install-dir=$out --root=$out
1700sed -i '/ = data\_files/d' setup.py
1701```
1702
1703### Rationale of non-existent global site-packages {#rationale-of-non-existent-global-site-packages}
1704
1705On most operating systems a global `site-packages` is maintained. This however
1706becomes problematic if you want to run multiple Python versions or have multiple
1707versions of certain libraries for your projects. Generally, you would solve such
1708issues by creating virtual environments using `virtualenv`.
1709
1710On Nix each package has an isolated dependency tree which, in the case of
1711Python, guarantees the right versions of the interpreter and libraries or
1712packages are available. There is therefore no need to maintain a global `site-packages`.
1713
1714If you want to create a Python environment for development, then the recommended
1715method is to use `nix-shell`, either with or without the `python.buildEnv`
1716function.
1717
1718### How to consume Python modules using pip in a virtual environment like I am used to on other Operating Systems? {#how-to-consume-python-modules-using-pip-in-a-virtual-environment-like-i-am-used-to-on-other-operating-systems}
1719
1720While this approach is not very idiomatic from Nix perspective, it can still be
1721useful when dealing with pre-existing projects or in situations where it's not
1722feasible or desired to write derivations for all required dependencies.
1723
1724This is an example of a `default.nix` for a `nix-shell`, which allows to consume
1725a virtual environment created by `venv`, and install Python modules through
1726`pip` the traditional way.
1727
1728Create this `default.nix` file, together with a `requirements.txt` and simply
1729execute `nix-shell`.
1730
1731```nix
1732with import <nixpkgs> { };
1733
1734let
1735 pythonPackages = python3Packages;
1736in pkgs.mkShell rec {
1737 name = "impurePythonEnv";
1738 venvDir = "./.venv";
1739 buildInputs = [
1740 # A Python interpreter including the 'venv' module is required to bootstrap
1741 # the environment.
1742 pythonPackages.python
1743
1744 # This executes some shell code to initialize a venv in $venvDir before
1745 # dropping into the shell
1746 pythonPackages.venvShellHook
1747
1748 # Those are dependencies that we would like to use from nixpkgs, which will
1749 # add them to PYTHONPATH and thus make them accessible from within the venv.
1750 pythonPackages.numpy
1751 pythonPackages.requests
1752
1753 # In this particular example, in order to compile any binary extensions they may
1754 # require, the Python modules listed in the hypothetical requirements.txt need
1755 # the following packages to be installed locally:
1756 taglib
1757 openssl
1758 git
1759 libxml2
1760 libxslt
1761 libzip
1762 zlib
1763 ];
1764
1765 # Run this command, only after creating the virtual environment
1766 postVenvCreation = ''
1767 unset SOURCE_DATE_EPOCH
1768 pip install -r requirements.txt
1769 '';
1770
1771 # Now we can execute any commands within the virtual environment.
1772 # This is optional and can be left out to run pip manually.
1773 postShellHook = ''
1774 # allow pip to install wheels
1775 unset SOURCE_DATE_EPOCH
1776 '';
1777
1778}
1779```
1780
1781In case the supplied venvShellHook is insufficient, or when Python 2 support is
1782needed, you can define your own shell hook and adapt to your needs like in the
1783following example:
1784
1785```nix
1786with import <nixpkgs> { };
1787
1788let
1789 venvDir = "./.venv";
1790 pythonPackages = python3Packages;
1791in pkgs.mkShell rec {
1792 name = "impurePythonEnv";
1793 buildInputs = [
1794 pythonPackages.python
1795 # Needed when using python 2.7
1796 # pythonPackages.virtualenv
1797 # ...
1798 ];
1799
1800 # This is very close to how venvShellHook is implemented, but
1801 # adapted to use 'virtualenv'
1802 shellHook = ''
1803 SOURCE_DATE_EPOCH=$(date +%s)
1804
1805 if [ -d "${venvDir}" ]; then
1806 echo "Skipping venv creation, '${venvDir}' already exists"
1807 else
1808 echo "Creating new venv environment in path: '${venvDir}'"
1809 # Note that the module venv was only introduced in python 3, so for 2.7
1810 # this needs to be replaced with a call to virtualenv
1811 ${pythonPackages.python.interpreter} -m venv "${venvDir}"
1812 fi
1813
1814 # Under some circumstances it might be necessary to add your virtual
1815 # environment to PYTHONPATH, which you can do here too;
1816 # PYTHONPATH=$PWD/${venvDir}/${pythonPackages.python.sitePackages}/:$PYTHONPATH
1817
1818 source "${venvDir}/bin/activate"
1819
1820 # As in the previous example, this is optional.
1821 pip install -r requirements.txt
1822 '';
1823}
1824```
1825
1826Note that the `pip install` is an imperative action. So every time `nix-shell`
1827is executed it will attempt to download the Python modules listed in
1828requirements.txt. However these will be cached locally within the `virtualenv`
1829folder and not downloaded again.
1830
1831### How to override a Python package from `configuration.nix`? {#how-to-override-a-python-package-from-configuration.nix}
1832
1833If you need to change a package's attribute(s) from `configuration.nix` you could do:
1834
1835```nix
1836 nixpkgs.config.packageOverrides = super: {
1837 python3 = super.python3.override {
1838 packageOverrides = python-self: python-super: {
1839 twisted = python-super.twisted.overridePythonAttrs (oldAttrs: {
1840 src = super.fetchPypi {
1841 pname = "Twisted";
1842 version = "19.10.0";
1843 hash = "sha256-c5S6fycq5yKnTz2Wnc9Zm8TvCTvDkgOHSKSQ8XJKUV0=";
1844 extension = "tar.bz2";
1845 };
1846 });
1847 };
1848 };
1849 };
1850```
1851
1852`pythonPackages.twisted` is now globally overridden.
1853All packages and also all NixOS services that reference `twisted`
1854(such as `services.buildbot-worker`) now use the new definition.
1855Note that `python-super` refers to the old package set and `python-self`
1856to the new, overridden version.
1857
1858To modify only a Python package set instead of a whole Python derivation, use
1859this snippet:
1860
1861```nix
1862 myPythonPackages = pythonPackages.override {
1863 overrides = self: super: {
1864 twisted = ...;
1865 };
1866 }
1867```
1868
1869### How to override a Python package using overlays? {#how-to-override-a-python-package-using-overlays}
1870
1871Use the following overlay template:
1872
1873```nix
1874self: super: {
1875 python = super.python.override {
1876 packageOverrides = python-self: python-super: {
1877 twisted = python-super.twisted.overrideAttrs (oldAttrs: {
1878 src = super.fetchPypi {
1879 pname = "Twisted";
1880 version = "19.10.0";
1881 hash = "sha256-c5S6fycq5yKnTz2Wnc9Zm8TvCTvDkgOHSKSQ8XJKUV0=";
1882 extension = "tar.bz2";
1883 };
1884 });
1885 };
1886 };
1887}
1888```
1889
1890### How to override a Python package for all Python versions using extensions? {#how-to-override-a-python-package-for-all-python-versions-using-extensions}
1891
1892The following overlay overrides the call to `buildPythonPackage` for the
1893`foo` package for all interpreters by appending a Python extension to the
1894`pythonPackagesExtensions` list of extensions.
1895
1896```nix
1897final: prev: {
1898 pythonPackagesExtensions = prev.pythonPackagesExtensions ++ [
1899 (
1900 python-final: python-prev: {
1901 foo = python-prev.foo.overridePythonAttrs (oldAttrs: {
1902 ...
1903 });
1904 }
1905 )
1906 ];
1907}
1908```
1909
1910### How to use Intel’s MKL with numpy and scipy? {#how-to-use-intels-mkl-with-numpy-and-scipy}
1911
1912MKL can be configured using an overlay. See the section "[Using overlays to
1913configure alternatives](#sec-overlays-alternatives-blas-lapack)".
1914
1915### What inputs do `setup_requires`, `install_requires` and `tests_require` map to? {#what-inputs-do-setup_requires-install_requires-and-tests_require-map-to}
1916
1917In a `setup.py` or `setup.cfg` it is common to declare dependencies:
1918
1919* `setup_requires` corresponds to `nativeBuildInputs`
1920* `install_requires` corresponds to `propagatedBuildInputs`
1921* `tests_require` corresponds to `nativeCheckInputs`
1922
1923## Contributing {#contributing}
1924
1925### Contributing guidelines {#contributing-guidelines}
1926
1927The following rules are desired to be respected:
1928
1929* Python libraries are called from `python-packages.nix` and packaged with
1930 `buildPythonPackage`. The expression of a library should be in
1931 `pkgs/development/python-modules/<name>/default.nix`.
1932* Python applications live outside of `python-packages.nix` and are packaged
1933 with `buildPythonApplication`.
1934* Make sure libraries build for all Python interpreters.
1935* By default we enable tests. Make sure the tests are found and, in the case of
1936 libraries, are passing for all interpreters. If certain tests fail they can be
1937 disabled individually. Try to avoid disabling the tests altogether. In any
1938 case, when you disable tests, leave a comment explaining why.
1939* Commit names of Python libraries should reflect that they are Python
1940 libraries, so write for example `pythonPackages.numpy: 1.11 -> 1.12`.
1941* Attribute names in `python-packages.nix` as well as `pname`s should match the
1942 library's name on PyPI, but be normalized according to [PEP
1943 0503](https://www.python.org/dev/peps/pep-0503/#normalized-names). This means
1944 that characters should be converted to lowercase and `.` and `_` should be
1945 replaced by a single `-` (foo-bar-baz instead of Foo__Bar.baz).
1946 If necessary, `pname` has to be given a different value within `fetchPypi`.
1947* Packages from sources such as GitHub and GitLab that do not exist on PyPI
1948 should not use a name that is already used on PyPI. When possible, they should
1949 use the package repository name prefixed with the owner (e.g. organization) name
1950 and using a `-` as delimiter.
1951* Attribute names in `python-packages.nix` should be sorted alphanumerically to
1952 avoid merge conflicts and ease locating attributes.
1953
1954## Package set maintenance {#python-package-set-maintenance}
1955
1956The whole Python package set has a lot of packages that do not see regular
1957updates, because they either are a very fragile component in the Python
1958ecosystem, like for example the `hypothesis` package, or packages that have
1959no maintainer, so maintenance falls back to the package set maintainers.
1960
1961### Updating packages in bulk {#python-package-bulk-updates}
1962
1963There is a tool to update alot of python libraries in bulk, it exists at
1964`maintainers/scripts/update-python-libraries` with this repository.
1965
1966It can quickly update minor or major versions for all packages selected
1967and create update commits, and supports the `fetchPypi`, `fetchurl` and
1968`fetchFromGitHub` fetchers. When updating lots of packages that are
1969hosted on GitHub, exporting a `GITHUB_API_TOKEN` is highly recommended.
1970
1971Updating packages in bulk leads to lots of breakages, which is why a
1972stabilization period on the `python-unstable` branch is required.
1973
1974If a package is fragile and often breaks during these bulks updates, it
1975may be reasonable to set `passthru.skipBulkUpdate = true` in the
1976derivation. This decision should not be made on a whim and should
1977always be supported by a qualifying comment.
1978
1979Once the branch is sufficiently stable it should normally be merged
1980into the `staging` branch.
1981
1982An exemplary call to update all python libraries between minor versions
1983would be:
1984
1985```ShellSession
1986$ maintainers/scripts/update-python-libraries --target minor --commit --use-pkgs-prefix pkgs/development/python-modules/**/default.nix
1987```
1988
1989## CPython Update Schedule {#python-cpython-update-schedule}
1990
1991With [PEP 602](https://www.python.org/dev/peps/pep-0602/), CPython now
1992follows a yearly release cadence. In nixpkgs, all supported interpreters
1993are made available, but only the most recent two
1994interpreters package sets are built; this is a compromise between being
1995the latest interpreter, and what the majority of the Python packages support.
1996
1997New CPython interpreters are released in October. Generally, it takes some
1998time for the majority of active Python projects to support the latest stable
1999interpreter. To help ease the migration for Nixpkgs users
2000between Python interpreters the schedule below will be used:
2001
2002| When | Event |
2003| --- | --- |
2004| After YY.11 Release | Bump CPython package set window. The latest and previous latest stable should now be built. |
2005| After YY.05 Release | Bump default CPython interpreter to latest stable. |
2006
2007In practice, this means that the Python community will have had a stable interpreter
2008for ~2 months before attempting to update the package set. And this will
2009allow for ~7 months for Python applications to support the latest interpreter.