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