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