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