Home Explore Blog CI



nixpkgs

18th chunk of `doc/languages-frameworks/python.section.md`
77c04e664b347df01ce1fe7bada5b5c263847daa34c0479a0000000100000fcf
The main benefits of using `pytestCheckHook` to construct `pytest` commands
is structuralization and eval-time accessibility.
This is especially helpful to select tests or specify flags conditionally:

```nix
{
  disabledTests =
    [
      # touches network
      "download"
      "update"
    ]
    ++ lib.optionals (pythonAtLeast "3.8") [
      # broken due to python3.8 async changes
      "async"
    ]
    ++ lib.optionals stdenv.buildPlatform.isDarwin [
      # can fail when building with other packages
      "socket"
    ];
}
```

#### Using pythonImportsCheck {#using-pythonimportscheck}

Although unit tests are highly preferred to validate correctness of a package, not
all packages have test suites that can be run easily, and some have none at all.
To help ensure the package still works, [`pythonImportsCheck`](#using-pythonimportscheck) can attempt to import
the listed modules.

```nix
{
  pythonImportsCheck = [
    "requests"
    "urllib"
  ];
}
```

roughly translates to:

```nix
{
  postCheck = ''
    PYTHONPATH=$out/${python.sitePackages}:$PYTHONPATH
    python -c "import requests; import urllib"
  '';
}
```

However, this is done in its own phase, and not dependent on whether [`doCheck = true;`](#var-stdenv-doCheck).

This can also be useful in verifying that the package doesn't assume commonly
present packages (e.g. `setuptools`).

#### Using pythonRelaxDepsHook {#using-pythonrelaxdepshook}

It is common for upstream to specify a range of versions for its package
dependencies. This makes sense, since it ensures that the package will be built
with a subset of packages that is well tested. However, this commonly causes
issues when packaging in Nixpkgs, because the dependencies that this package
may need are too new or old for the package to build correctly. We also cannot
package multiple versions of the same package since this may cause conflicts
in `PYTHONPATH`.

One way to side step this issue is to relax the dependencies. This can be done
by either removing the package version range or by removing the package
declaration entirely. This can be done using the `pythonRelaxDepsHook` hook. For
example, given the following `requirements.txt` file:

```
pkg1<1.0
pkg2
pkg3>=1.0,<=2.0
```

we can do:

```nix
{
  pythonRelaxDeps = [
    "pkg1"
    "pkg3"
  ];
  pythonRemoveDeps = [
    "pkg2"
  ];
}
```

which would result in the following `requirements.txt` file:

```
pkg1
pkg3
```

Another option is to pass `true`, that will relax/remove all dependencies, for
example:

```nix
{
  pythonRelaxDeps = true;
}
```

which would result in the following `requirements.txt` file:

```
pkg1
pkg2
pkg3
```

In general you should always use `pythonRelaxDeps`, because `pythonRemoveDeps`
will convert build errors into runtime errors. However `pythonRemoveDeps` may
still be useful in exceptional cases, and also to remove dependencies wrongly
declared by upstream (for example, declaring `black` as a runtime dependency
instead of a dev dependency).

Keep in mind that while the examples above are done with `requirements.txt`,
`pythonRelaxDepsHook` works by modifying the resulting wheel file, so it should
work with any of the [existing hooks](#setup-hooks).

The `pythonRelaxDepsHook` has no effect on build time dependencies, such as
those specified in `build-system`. If a package requires incompatible build
time dependencies, they should be removed in `postPatch` through
`substituteInPlace` or similar.

For ease of use, both `buildPythonPackage` and `buildPythonApplication` will
automatically add `pythonRelaxDepsHook` if either `pythonRelaxDeps` or
`pythonRemoveDeps` is specified.

#### Using unittestCheckHook {#using-unittestcheckhook}

`unittestCheckHook` is a hook which will set up (or configure) a [`checkPhase`](#ssec-check-phase) to run `python -m unittest discover`:

```nix
{
  nativeCheckInputs = [
    unittestCheckHook
  ];

  unittestFlags = [
    "-s"
    "tests"
    "-v"
  ];
}
```

`pytest` is compatible with `unittest`, so in most cases you can use `pytestCheckHook` instead.

Title: Using pythonImportsCheck, pythonRelaxDepsHook, and unittestCheckHook
Summary
This section explains the usage of `pythonImportsCheck` to verify the import of modules, `pythonRelaxDepsHook` to modify package dependencies by removing version ranges or declarations, and `unittestCheckHook` to run unittest discovery. It emphasizes the benefits and trade-offs of using each hook, including the structuralization and eval-time accessibility provided by `pytestCheckHook` and the handling of build vs. runtime dependencies.