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