- Rewrite current documentation - Add introduction/tutorial - Convert to markdownwip/yesman
parent
ce6a1a6cea
commit
4c1525c1f8
@ -0,0 +1,714 @@ |
||||
# Python |
||||
|
||||
## User Guide |
||||
|
||||
Several versions of Python are available on Nix as well as a high amount of |
||||
packages. The default interpreter is CPython 2.7. |
||||
|
||||
### Using Python |
||||
|
||||
#### Installing Python and packages |
||||
|
||||
It is important to make a distinction between Python packages that are |
||||
used as libraries, and applications that are written in Python. |
||||
|
||||
Applications on Nix are installed typically into your user |
||||
profile imperatively using `nix-env -i`, and on NixOS declaratively by adding the |
||||
package name to `environment.systemPackages` in `/etc/nixos/configuration.nix`. |
||||
Dependencies such as libraries are automatically installed and should not be |
||||
installed explicitly. |
||||
|
||||
The same goes for Python applications and libraries. Python applications can be |
||||
installed in your profile, but Python libraries you would like to use to develop |
||||
cannot. If you do install libraries in your profile, then you will end up with |
||||
import errors. |
||||
|
||||
#### Python environments using `nix-shell` |
||||
|
||||
The recommended method for creating Python environments for development is with |
||||
`nix-shell`. Executing |
||||
|
||||
```sh |
||||
$ nix-shell -p python35Packages.numpy python35Packages.toolz |
||||
``` |
||||
|
||||
opens a Nix shell which has available the requested packages and dependencies. |
||||
Now you can launch the Python interpreter (which is itself a dependency) |
||||
|
||||
```sh |
||||
[nix-shell:~] python3 |
||||
``` |
||||
|
||||
If the packages were not available yet in the Nix store, Nix would download or |
||||
build them automatically. A convenient option with `nix-shell` is the `--run` |
||||
option, with which you can execute a command in the `nix-shell`. Let's say we |
||||
want the above environment and directly run the Python interpreter |
||||
|
||||
```sh |
||||
$ nix-shell -p python35Packages.numpy python35Packages.toolz --run "python3" |
||||
``` |
||||
|
||||
This way you can use the `--run` option also to directly run a script |
||||
|
||||
```sh |
||||
$ nix-shell -p python35Packages.numpy python35Packages.toolz --run "python3 myscript.py" |
||||
``` |
||||
|
||||
In fact, for this specific use case there is a more convenient method. You can |
||||
add a [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)) to your script |
||||
specifying which dependencies Nix shell needs. With the following shebang, you |
||||
can use `nix-shell myscript.py` and it will make available all dependencies and |
||||
run the script in the `python3` shell. |
||||
|
||||
```py |
||||
#! /usr/bin/env nix-shell |
||||
#! nix-shell -i python3 -p python3Packages.numpy |
||||
|
||||
import numpy |
||||
|
||||
print(numpy.__version__) |
||||
``` |
||||
|
||||
Likely you do not want to type your dependencies each and every time. What you |
||||
can do is write a simple Nix expression which sets up an environment for you, |
||||
requiring you only to type `nix-shell`. Say we want to have Python 3.5, `numpy` |
||||
and `toolz`, like before, in an environment. With a `shell.nix` file |
||||
containing |
||||
|
||||
```nix |
||||
with import <nixpkgs> {}; |
||||
|
||||
(pkgs.python35.buildEnv.override { |
||||
extraLibs = with pkgs.python35Packages; [ numpy toolz ]; |
||||
}).env |
||||
``` |
||||
executing `nix-shell` gives you again a Nix shell from which you can run Python. |
||||
|
||||
What's happening here? |
||||
|
||||
1. We begin with importing the Nix Packages collections. `import <nixpkgs>` import the `<nixpkgs>` function, `{}` calls it and the `with` statement brings all attributes of `nixpkgs` in the local scope. Therefore we can now use `pkgs`. |
||||
2. Then we create a Python 3.5 environment with `pkgs.buildEnv`. Because we want to use it with a custom set of Python packages, we override it. |
||||
3. The `extraLibs` argument of the original `buildEnv` function can be used to specify which packages should be included. We want `numpy` and `toolz`. Again, we use the `with` statement to bring a set of attributes into the local scope. |
||||
4. And finally, for in interactive use we return the environment. |
||||
|
||||
### Developing with Python |
||||
|
||||
|
||||
Now that you know how to get a working Python environment on Nix, it is time to go forward and start actually developing with Python. |
||||
We will first have a look at how Python packages are packaged on Nix. Then, we will look how you can use development mode with your code. |
||||
|
||||
#### Python packaging on Nix |
||||
|
||||
On Nix all packages are built by functions. The main function in Nix for building Python packages is [`buildPythonPackage`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/python-modules/generic/default.nix). |
||||
Let's see how we would build the `toolz` package. According to [`python-packages.nix`](https://raw.githubusercontent.com/NixOS/nixpkgs/master/pkgs/top-level/python-packages.nix) `toolz` is build using |
||||
|
||||
```nix |
||||
toolz = buildPythonPackage rec{ |
||||
name = "toolz-${version}"; |
||||
version = "0.7.4"; |
||||
|
||||
src = pkgs.fetchurl{ |
||||
url = "https://pypi.python.org/packages/source/t/toolz/toolz-${version}.tar.gz"; |
||||
sha256 = "43c2c9e5e7a16b6c88ba3088a9bfc82f7db8e13378be7c78d6c14a5f8ed05afd"; |
||||
}; |
||||
|
||||
meta = { |
||||
homepage = "http://github.com/pytoolz/toolz/"; |
||||
description = "List processing tools and functional utilities"; |
||||
license = licenses.bsd3; |
||||
maintainers = with maintainers; [ fridh ]; |
||||
}; |
||||
}; |
||||
``` |
||||
|
||||
What happens here? The function `buildPythonPackage` is called and as argument |
||||
it accepts a set. In this case the set is a recursive set ([`rec`](http://nixos.org/nix/manual/#sec-constructs)). |
||||
One of the arguments is the name of the package, which consists of a basename |
||||
(generally following the name on PyPi) and a version. Another argument, `src` |
||||
specifies the source, which in this case is fetched from an url. `fetchurl` not |
||||
only downloads the target file, but also validates its hash. Furthermore, we |
||||
specify some (optional) [meta information](http://nixos.org/nixpkgs/manual/#chap-meta). |
||||
|
||||
The output of the function is a derivation, which is an attribute with the name |
||||
`toolz` of the set `pythonPackages`. Actually, sets are created for all interpreter versions, |
||||
so `python27Packages`, `python34Packages`, `python35Packages` and `pypyPackages`. |
||||
|
||||
The above example works when you're directly working on |
||||
`pkgs/top-level/python-packages.nix` in the Nixpkgs repository. Often though, |
||||
you will want to test a Nix expression outside of the Nixpkgs tree. If you |
||||
create a `shell.nix` file with the following contents |
||||
|
||||
```nix |
||||
with import <nixpkgs> {}; |
||||
|
||||
pkgs.python35Packages.buildPythonPackage rec { |
||||
name = "toolz-${version}"; |
||||
version = "0.7.4"; |
||||
|
||||
src = pkgs.fetchurl{ |
||||
url = "https://pypi.python.org/packages/source/t/toolz/toolz-${version}.tar.gz"; |
||||
sha256 = "43c2c9e5e7a16b6c88ba3088a9bfc82f7db8e13378be7c78d6c14a5f8ed05afd"; |
||||
}; |
||||
|
||||
meta = { |
||||
homepage = "http://github.com/pytoolz/toolz/"; |
||||
description = "List processing tools and functional utilities"; |
||||
license = licenses.bsd3; |
||||
maintainers = with maintainers; [ fridh ]; |
||||
}; |
||||
} |
||||
``` |
||||
|
||||
and then execute `nix-shell` will result in an environment in which you can use |
||||
Python 3.5 and the `toolz` package. As you can see we had to explicitly mention |
||||
for which Python version we want to build a package. |
||||
|
||||
The above example considered only a single package. Generally you will want to use multiple packages. |
||||
If we create a `shell.nix` file with the following contents |
||||
|
||||
```nix |
||||
with import <nixpkgs> {}; |
||||
|
||||
( let |
||||
toolz = pkgs.python35Packages.buildPythonPackage rec { |
||||
name = "toolz-${version}"; |
||||
version = "0.7.4"; |
||||
|
||||
src = pkgs.fetchurl{ |
||||
url = "https://pypi.python.org/packages/source/t/toolz/toolz-${version}.tar.gz"; |
||||
sha256 = "43c2c9e5e7a16b6c88ba3088a9bfc82f7db8e13378be7c78d6c14a5f8ed05afd"; |
||||
}; |
||||
|
||||
meta = { |
||||
homepage = "http://github.com/pytoolz/toolz/"; |
||||
description = "List processing tools and functional utilities"; |
||||
license = licenses.bsd3; |
||||
maintainers = with maintainers; [ fridh ]; |
||||
}; |
||||
}; |
||||
|
||||
in pkgs.python35.buildEnv.override rec { |
||||
|
||||
extraLibs = [ pkgs.python35Packages.numpy toolz ]; |
||||
} |
||||
).env |
||||
``` |
||||
|
||||
and again execute `nix-shell`, then we get a Python 3.5 environment with our |
||||
locally defined package as well as `numpy` which is build according to the |
||||
definition in Nixpkgs. What did we do here? Well, we took the Nix expression |
||||
that we used earlier to build a Python environment, and said that we wanted to |
||||
include our own version of `toolz`. To introduce our own package in the scope of |
||||
`buildEnv.override` we used a |
||||
[`let`](http://nixos.org/nix/manual/#sec-constructs) expression. |
||||
|
||||
### Handling dependencies |
||||
|
||||
Our example, `toolz`, doesn't have any dependencies on other Python |
||||
packages or system libraries. According to the manual, `buildPythonPackage` |
||||
uses the arguments `buildInputs` and `propagatedBuildInputs` to specify dependencies. If something is |
||||
exclusively a build-time dependency, then the dependency should be included as a |
||||
`buildInput`, but if it is (also) a runtime dependency, then it should be added |
||||
to `propagatedBuildInputs`. Test dependencies are considered build-time dependencies. |
||||
|
||||
The following example shows which arguments are given to `buildPythonPackage` in |
||||
order to build [`datashape`](https://github.com/blaze/datashape). |
||||
|
||||
```nix |
||||
datashape = buildPythonPackage rec { |
||||
name = "datashape-${version}"; |
||||
version = "0.4.7"; |
||||
|
||||
src = pkgs.fetchurl { |
||||
url = "https://pypi.python.org/packages/source/D/DataShape/${name}.tar.gz"; |
||||
sha256 = "14b2ef766d4c9652ab813182e866f493475e65e558bed0822e38bf07bba1a278"; |
||||
}; |
||||
|
||||
buildInputs = with self; [ pytest ]; |
||||
propagatedBuildInputs = with self; [ numpy multipledispatch dateutil ]; |
||||
|
||||
meta = { |
||||
homepage = https://github.com/ContinuumIO/datashape; |
||||
description = "A data description language"; |
||||
license = licenses.bsd2; |
||||
maintainers = with maintainers; [ fridh ]; |
||||
}; |
||||
}; |
||||
``` |
||||
|
||||
We can see several runtime dependencies, `numpy`, `multipledispatch`, and |
||||
`dateutil`. Furthermore, we have one `buildInput`, i.e. `pytest`. `pytest` is a |
||||
test runner and is only used during the `checkPhase` and is therefore not added |
||||
to `propagatedBuildInputs`. |
||||
|
||||
In the previous case we had only dependencies on other Python packages to consider. |
||||
Occasionally you have also system libraries to consider. E.g., `lxml` provides |
||||
Python bindings to `libxml2` and `libxslt`. These libraries are only required |
||||
when building the bindings and are therefore added as `buildInputs`. |
||||
|
||||
```nix |
||||
lxml = buildPythonPackage rec { |
||||
name = "lxml-3.4.4"; |
||||
|
||||
src = pkgs.fetchurl { |
||||
url = "http://pypi.python.org/packages/source/l/lxml/${name}.tar.gz"; |
||||
sha256 = "16a0fa97hym9ysdk3rmqz32xdjqmy4w34ld3rm3jf5viqjx65lxk"; |
||||
}; |
||||
|
||||
buildInputs = with self; [ pkgs.libxml2 pkgs.libxslt ]; |
||||
|
||||
meta = { |
||||
description = "Pythonic binding for the libxml2 and libxslt libraries"; |
||||
homepage = http://lxml.de; |
||||
license = licenses.bsd3; |
||||
maintainers = with maintainers; [ sjourdois ]; |
||||
}; |
||||
}; |
||||
``` |
||||
|
||||
In this example `lxml` and Nix are able to work out exactly where the relevant |
||||
files of the dependencies are. This is not always the case. |
||||
|
||||
The example below shows bindings to The Fastest Fourier Transform in the West, commonly known as |
||||
FFTW. On Nix we have separate packages of FFTW for the different types of floats |
||||
(`"single"`, `"double"`, `"long-double"`). The bindings need all three types, |
||||
and therefore we add all three as `buildInputs`. The bindings don't expect to |
||||
find each of them in a different folder, and therefore we have to set `LDFLAGS` |
||||
and `CFLAGS`. |
||||
|
||||
```nix |
||||
pyfftw = buildPythonPackage rec { |
||||
name = "pyfftw-${version}"; |
||||
version = "0.9.2"; |
||||
|
||||
src = pkgs.fetchurl { |
||||
url = "https://pypi.python.org/packages/source/p/pyFFTW/pyFFTW-${version}.tar.gz"; |
||||
sha256 = "f6bbb6afa93085409ab24885a1a3cdb8909f095a142f4d49e346f2bd1b789074"; |
||||
}; |
||||
|
||||
buildInputs = [ pkgs.fftw pkgs.fftwFloat pkgs.fftwLongDouble]; |
||||
|
||||
propagatedBuildInputs = with self; [ numpy scipy ]; |
||||
|
||||
# Tests cannot import pyfftw. pyfftw works fine though. |
||||
doCheck = false; |
||||
|
||||
LDFLAGS="-L${pkgs.fftw}/lib -L${pkgs.fftwFloat}/lib -L${pkgs.fftwLongDouble}/lib" |
||||
CFLAGS="-I${pkgs.fftw}/include -I${pkgs.fftwFloat}/include -I${pkgs.fftwLongDouble}/include" |
||||
''; |
||||
|
||||
meta = { |
||||
description = "A pythonic wrapper around FFTW, the FFT library, presenting a unified interface for all the supported transforms"; |
||||
homepage = http://hgomersall.github.com/pyFFTW/; |
||||
license = with licenses; [ bsd2 bsd3 ]; |
||||
maintainer = with maintainers; [ fridh ]; |
||||
}; |
||||
}; |
||||
``` |
||||
Note also the line `doCheck = false;`, we explicitly disabled running the test-suite. |
||||
|
||||
|
||||
#### Develop local package |
||||
|
||||
As a Python developer you're likely aware of [development mode](http://pythonhosted.org/setuptools/setuptools.html#development-mode) (`python setup.py develop`); |
||||
instead of installing the package this command creates a special link to the project code. |
||||
That way, you can run updated code without having to reinstall after each and every change you make. |
||||
Development mode is also available on Nix as [explained](http://nixos.org/nixpkgs/manual/#ssec-python-development) in the Nixpkgs manual. |
||||
Let's see how you can use it. |
||||
|
||||
In the previous Nix expression the source was fetched from an url. We can also refer to a local source instead using |
||||
|
||||
```nix |
||||
src = ./path/to/source/tree; |
||||
``` |
||||
|
||||
If we create a `shell.nix` file which calls `buildPythonPackage`, and if `src` |
||||
is a local source, and if the local source has a `setup.py`, then development |
||||
mode is activated. |
||||
|
||||
In the following example we create a simple environment that |
||||
has a Python 3.5 version of our package in it, as well as its dependencies and |
||||
other packages we like to have in the environment, all specified with `propagatedBuildInputs`. |
||||
Indeed, we can just add any package we like to have in our environment to `propagatedBuildInputs`. |
||||
|
||||
```nix |
||||
with import <nixpkgs>; |
||||
with pkgs.python35Packages; |
||||
|
||||
buildPythonPackage rec { |
||||
name = "mypackage"; |
||||
src = ./path/to/package/source; |
||||
propagatedBuildInputs = [ pytest numpy pkgs.libsndfile ]; |
||||
}; |
||||
``` |
||||
|
||||
It is important to note that due to how development mode is implemented on Nix it is not possible to have multiple packages simultaneously in development mode. |
||||
|
||||
|
||||
### Organising your packages |
||||
|
||||
So far we discussed how you can use Python on Nix, and how you can develop with |
||||
it. We've looked at how you write expressions to package Python packages, and we |
||||
looked at how you can create environments in which specified packages are |
||||
available. |
||||
|
||||
At some point you'll likely have multiple packages which you would |
||||
like to be able to use in different projects. In order to minimise unnecessary |
||||
duplication we now look at how you can maintain yourself a repository with your |
||||
own packages. The important functions here are `import` and `callPackage`. |
||||
|
||||
### Including a derivation using `callPackage` |
||||
|
||||
Earlier we created a Python environment using `buildEnv`, and included the |
||||
`toolz` package via a `let` expression. |
||||
Let's split the package definition from the environment definition. |
||||
|
||||
We first create a function that builds `toolz` in `~/path/to/toolz/release.nix` |
||||
|
||||
```nix |
||||
{ pkgs, buildPythonPackage }: |
||||
|
||||
buildPythonPackage rec { |
||||
name = "toolz-${version}"; |
||||
version = "0.7.4"; |
||||
|
||||
src = pkgs.fetchurl{ |
||||
url = "https://pypi.python.org/packages/source/t/toolz/toolz-${version}.tar.gz"; |
||||
sha256 = "43c2c9e5e7a16b6c88ba3088a9bfc82f7db8e13378be7c78d6c14a5f8ed05afd"; |
||||
}; |
||||
|
||||
meta = { |
||||
homepage = "http://github.com/pytoolz/toolz/"; |
||||
description = "List processing tools and functional utilities"; |
||||
license = licenses.bsd3; |
||||
maintainers = with maintainers; [ fridh ]; |
||||
}; |
||||
}; |
||||
``` |
||||
|
||||
It takes two arguments, `pkgs` and `buildPythonPackage`. |
||||
We now call this function using `callPackage` in the definition of our environment |
||||
|
||||
```nix |
||||
with import <nixpkgs> {}; |
||||
|
||||
( let |
||||
toolz = pkgs.callPackage ~/path/to/toolz/release.nix { pkgs=pkgs; buildPythonPackage=pkgs.python35Packages.buildPythonPackage; }; |
||||
in pkgs.python35.buildEnv.override rec { |
||||
extraLibs = [ pkgs.python35Packages.numpy toolz ]; |
||||
} |
||||
).env |
||||
``` |
||||
|
||||
Important to remember is that the Python version for which the package is made |
||||
depends on the `python` derivation that is passed to `buildPythonPackage`. Nix |
||||
tries to automatically pass arguments when possible, which is why generally you |
||||
don't explicitly define which `python` derivation should be used. In the above |
||||
example we use `buildPythonPackage` that is part of the set `python35Packages`, |
||||
and in this case the `python35` interpreter is automatically used. |
||||
|
||||
|
||||
|
||||
## Reference |
||||
|
||||
### Interpreters |
||||
|
||||
Versions 2.6, 2.7, 3.3, 3.4 and 3.5 of the CPython interpreter are available on |
||||
Nix and are available as `python26`, `python27`, `python33`, `python34` and |
||||
`python35`. The PyPy interpreter is also available as `pypy`. Currently, the |
||||
aliases `python` and `python3` correspond to respectively `python27` and |
||||
`python35`. The Nix expressions for the interpreters can be found in |
||||
`pkgs/development/interpreters/python`. |
||||
|
||||
|
||||
#### Missing modules standard library |
||||
|
||||
The interpreters `python26` and `python27` do not include modules that |
||||
require external dependencies. This is done in order to reduce the closure size. |
||||
The following modules need to be added as `buildInput` explicitly: |
||||
|
||||
* `python.modules.bsddb` |
||||
* `python.modules.curses` |
||||
* `python.modules.curses_panel` |
||||
* `python.modules.crypt` |
||||
* `python.modules.gdbm` |
||||
* `python.modules.sqlite3` |
||||
* `python.modules.tkinter` |
||||
* `python.modules.readline` |
||||
|
||||
For convenience `python27Full` and `python26Full` are provided with all |
||||
modules included. |
||||
|
||||
All packages depending on any Python interpreter get appended |
||||
`out/{python.sitePackages}` to `$PYTHONPATH` if such directory |
||||
exists. |
||||
|
||||
#### Attributes on interpreters packages |
||||
|
||||
Each interpreter has the following attributes: |
||||
|
||||
- `libPrefix`. Name of the folder in `${python}/lib/` for corresponding interpreter. |
||||
- `interpreter`. Alias for `${python}/bin/${executable}`. |
||||
- `buildEnv`. Function to build python interpreter environments with extra packages bundled together. See section *python.buildEnv function* for usage and documentation. |
||||
- `sitePackages`. Alias for `lib/${libPrefix}/site-packages`. |
||||
- `executable`. Name of the interpreter executable, ie `python3.4`. |
||||
|
||||
### Building packages and applications |
||||
|
||||
Python packages (libraries) and applications that use `setuptools` or |
||||
`distutils` are typically built with respectively the `buildPythonPackage` and |
||||
`buildPythonApplication` functions. |
||||
|
||||
All Python packages reside in `pkgs/top-level/python-packages.nix` and all |
||||
applications elsewhere. Some packages are also defined in |
||||
`pkgs/development/python-modules`. It is important that these packages are |
||||
called in `pkgs/top-level/python-packages.nix` and not elsewhere, to guarantee |
||||
the right version of the package is built. |
||||
|
||||
Based on the packages defined in `pkgs/top-level/python-packages.nix` an |
||||
attribute set is created for each available Python interpreter. The available |
||||
sets are |
||||
|
||||
* `pkgs.python26Packages` |
||||
* `pkgs.python27Packages` |
||||
* `pkgs.python33Packages` |
||||
* `pkgs.python34Packages` |
||||
* `pkgs.python35Packages` |
||||
* `pkgs.pypyPackages` |
||||
|
||||
and the aliases |
||||
|
||||
* `pkgs.pythonPackages` pointing to `pkgs.python27Packages` |
||||
* `pkgs.python3Packages` pointing to `pkgs.python35Packages` |
||||
|
||||
#### `buildPythonPackage` function |
||||
|
||||
The `buildPythonPackage` function is implemented in |
||||
`pkgs/development/python-modules/generic/default.nix` |
||||
|
||||
and can be used as: |
||||
|
||||
twisted = buildPythonPackage { |
||||
name = "twisted-8.1.0"; |
||||
|
||||
src = pkgs.fetchurl { |
||||
url = http://tmrc.mit.edu/mirror/twisted/Twisted/8.1/Twisted-8.1.0.tar.bz2; |
||||
sha256 = "0q25zbr4xzknaghha72mq57kh53qw1bf8csgp63pm9sfi72qhirl"; |
||||
}; |
||||
|
||||
propagatedBuildInputs = [ self.ZopeInterface ]; |
||||
|
||||
meta = { |
||||
homepage = http://twistedmatrix.com/; |
||||
description = "Twisted, an event-driven networking engine written in Python"; |
||||
license = stdenv.lib.licenses.mit; }; |
||||
}; |
||||
|
||||
The `buildPythonPackage` mainly does four things: |
||||
|
||||
* In the `buildPhase`, it calls `${python.interpreter} setup.py bdist_wheel` to build a wheel binary zipfile. |
||||
* In the `installPhase`, it installs the wheel file using `pip install *.whl`. |
||||
* In the `postFixup` phase, the `wrapPythonPrograms` bash function is called to wrap all programs in the `$out/bin/*` directory to include `$PYTHONPATH` and `$PATH` environment variables. |
||||
* In the `installCheck` phase, `${python.interpreter} setup.py test` is ran. |
||||
|
||||
As in Perl, dependencies on other Python packages can be specified in the |
||||
`buildInputs` and `propagatedBuildInputs` attributes. If something is |
||||
exclusively a build-time dependency, use `buildInputs`; if it’s (also) a runtime |
||||
dependency, use `propagatedBuildInputs`. |
||||
|
||||
By default tests are run because `doCheck = true`. Test dependencies, like |
||||
e.g. the test runner, should be added to `buildInputs`. |
||||
|
||||
By default `meta.platforms` is set to the same value |
||||
as the interpreter unless overriden otherwise. |
||||
|
||||
##### `buildPythonPackage` parameters |
||||
|
||||
All parameters from `mkDerivation` function are still supported. |
||||
|
||||
* `namePrefix`: Prepended text to `${name}` parameter. Defaults to `"python3.3-"` for Python 3.3, etc. Set it to `""` if you're packaging an application or a command line tool. |
||||
* `disabled`: If `true`, package is not build for particular python interpreter version. Grep around `pkgs/top-level/python-packages.nix` for examples. |
||||
* `setupPyBuildFlags`: List of flags passed to `setup.py build_ext` command. |
||||
* `pythonPath`: List of packages to be added into `$PYTHONPATH`. Packages in `pythonPath` are not propagated (contrary to `propagatedBuildInputs`). |
||||
* `preShellHook`: Hook to execute commands before `shellHook`. |
||||
* `postShellHook`: Hook to execute commands after `shellHook`. |
||||
* `makeWrapperArgs`: A list of strings. Arguments to be passed to `makeWrapper`, which wraps generated binaries. By default, the arguments to `makeWrapper` set `PATH` and `PYTHONPATH` environment variables before calling the binary. Additional arguments here can allow a developer to set environment variables which will be available when the binary is run. For example, `makeWrapperArgs = ["--set FOO BAR" "--set BAZ QUX"]`. |
||||
* `installFlags`: A list of strings. Arguments to be passed to `pip install`. To pass options to `python setup.py install`, use `--install-option`. E.g., `installFlags=["--install-option='--cpp_implementation'"]. |
||||
|
||||
#### `buildPythonApplication` function |
||||
|
||||
The `buildPythonApplication` function is practically the same as `buildPythonPackage`. |
||||
The difference is that `buildPythonPackage` by default prefixes the names of the packages with the version of the interpreter. |
||||
Because with an application we're not interested in multiple version the prefix is dropped. |
||||
|
||||
#### python.buildEnv function |
||||
|
||||
Python environments can be created using the low-level `pkgs.buildEnv` function. |
||||
This example shows how to create an environment that has the Pyramid Web Framework. |
||||
Saving the following as `default.nix` |
||||
|
||||
with import {}; |
||||
|
||||
python.buildEnv.override { |
||||
extraLibs = [ pkgs.pythonPackages.pyramid ]; |
||||
ignoreCollisions = true; |
||||
} |
||||
|
||||
and running `nix-build` will create |
||||
|
||||
/nix/store/cf1xhjwzmdki7fasgr4kz6di72ykicl5-python-2.7.8-env |
||||
|
||||
with wrapped binaries in `bin/`. |
||||
|
||||
You can also use the `env` attribute to create local environments with needed |
||||
packages installed. This is somewhat comparable to `virtualenv`. For example, |
||||
running `nix-shell` with the following `shell.nix` |
||||
|
||||
with import {}; |
||||
|
||||
(python3.buildEnv.override { |
||||
extraLibs = with python3Packages; [ numpy requests ]; |
||||
}).env |
||||
|
||||
will drop you into a shell where Python will have the |
||||
specified packages in its path. |
||||
|
||||
|
||||
##### `python.buildEnv` arguments |
||||
|
||||
* `extraLibs`: List of packages installed inside the environment. |
||||
* `postBuild`: Shell command executed after the build of environment. |
||||
* `ignoreCollisions`: Ignore file collisions inside the environment (default is `false`). |
||||
|
||||
### Development mode |
||||
|
||||
Development or editable mode is supported. To develop Python packages |
||||
`buildPythonPackage` has additional logic inside `shellPhase` to run `pip |
||||
install -e . --prefix $TMPDIR/`for the package. |
||||
|
||||
Warning: `shellPhase` is executed only if `setup.py` exists. |
||||
|
||||
Given a `default.nix`: |
||||
|
||||
with import {}; |
||||
|
||||
buildPythonPackage { name = "myproject"; |
||||
|
||||
buildInputs = with pkgs.pythonPackages; [ pyramid ]; |
||||
|
||||
src = ./.; } |
||||
|
||||
Running `nix-shell` with no arguments should give you |
||||
the environment in which the package would be build with |
||||
`nix-build`. |
||||
|
||||
Shortcut to setup environments with C headers/libraries and python packages: |
||||
|
||||
$ nix-shell -p pythonPackages.pyramid zlib libjpeg git |
||||
|
||||
Note: There is a boolean value `lib.inNixShell` set to `true` if nix-shell is invoked. |
||||
|
||||
### Tools |
||||
|
||||
Packages inside nixpkgs are written by hand. However many tools exist in |
||||
community to help save time. No tool is preferred at the moment. |
||||
|
||||
- [python2nix](https://github.com/proger/python2nix) by Vladimir Kirillov |
||||
- [pypi2nix](https://github.com/garbas/pypi2nix) by Rok Garbas |
||||
- [pypi2nix](https://github.com/offlinehacker/pypi2nix) by Jaka Hudoklin |
||||
|
||||
## FAQ |
||||
|
||||
### How to solve circular dependencies? |
||||
|
||||
Consider the packages `A` and `B` that depend on each other. When packaging `B`, |
||||
a solution is to override package `A` not to depend on `B` as an input. The same |
||||
should also be done when packaging `A`. |
||||
|
||||
### How to override a Python package? |
||||
|
||||
Recursively updating a package can be done with `pkgs.overridePackages` as explained in the Nixpkgs manual. |
||||
Python attribute sets are created for each interpreter version. We will therefore override the attribute set for the interpreter version we're interested. |
||||
In the following example we change the name of the package `pandas` to `foo`. |
||||
``` |
||||
newpkgs = pkgs.overridePackages(self: super: rec { |
||||
python35Packages = super.python35Packages.override { |
||||
self = python35Packages // { pandas = python35Packages.pandas.override{name="foo";};}; |
||||
}; |
||||
}); |
||||
``` |
||||
This can be tested with |
||||
``` |
||||
with import <nixpkgs> {}; |
||||
|
||||
(let |
||||
|
||||
newpkgs = pkgs.overridePackages(self: super: rec { |
||||
python35Packages = super.python35Packages.override { |
||||
self = python35Packages // { pandas = python35Packages.pandas.override{name="foo";};}; |
||||
}; |
||||
}); |
||||
in newpkgs.python35.buildEnv.override{ |
||||
extraLibs = [newpkgs.python35Packages.blaze ]; |
||||
}).env |
||||
``` |
||||
A typical use case is to switch to another version of a certain package. For example, in the Nixpkgs repository we have multiple versions of `django` and `scipy`. |
||||
In the following example we use a different version of `scipy`. All packages in `newpkgs` will now use the updated `scipy` version. |
||||
``` |
||||
with import <nixpkgs> {}; |
||||
|
||||
(let |
||||
|
||||
newpkgs = pkgs.overridePackages(self: super: rec { |
||||
python35Packages = super.python35Packages.override { |
||||
self = python35Packages // { scipy = python35Packages.scipy_0_16;}; |
||||
}; |
||||
}); |
||||
in pkgs.python35.buildEnv.override{ |
||||
extraLibs = [newpkgs.python35Packages.blaze ]; |
||||
}).env |
||||
``` |
||||
The requested package `blaze` depends upon `pandas` which itself depends on `scipy`. |
||||
|
||||
|
||||
### `install_data` / `data_files` problems |
||||
|
||||
If you get the following error: |
||||
|
||||
could not create '/nix/store/6l1bvljpy8gazlsw2aw9skwwp4pmvyxw-python-2.7.8/etc': |
||||
Permission denied |
||||
|
||||
This is a [known bug](https://bitbucket.org/pypa/setuptools/issue/130/install_data-doesnt-respect-prefix) in setuptools. |
||||
Setuptools `install_data` does not respect `--prefix`. An example of such package using the feature is `pkgs/tools/X11/xpra/default.nix`. |
||||
As workaround install it as an extra `preInstall` step: |
||||
|
||||
${python.interpreter} setup.py install_data --install-dir=$out --root=$out |
||||
sed -i '/ = data\_files/d' setup.py |
||||
|
||||
|
||||
### Rationale of non-existent global site-packages |
||||
|
||||
On most operating systems a global `site-packages` is maintained. This however |
||||
becomes problematic if you want to run multiple Python versions or have multiple |
||||
versions of certain libraries for your projects. Generally, you would solve such |
||||
issues by creating virtual environments using `virtualenv`. |
||||
|
||||
On Nix each package has an isolated dependency tree which, in the case of |
||||
Python, guarantees the right versions of the interpreter and libraries or |
||||
packages are available. There is therefore no need to maintain a global `site-packages`. |
||||
|
||||
If you want to create a Python environment for development, then the recommended |
||||
method is to use `nix-shell`, either with or without the `python.buildEnv` |
||||
function. |
||||
|
||||
|
||||
## Contributing |
||||
|
||||
### Contributing guidelines |
||||
|
||||
Following rules are desired to be respected: |
||||
|
||||
* Make sure package builds for all python interpreters. Use `disabled` argument to `buildPythonPackage` to set unsupported interpreters. |
||||
* If tests need to be disabled for a package, make sure you leave a comment about reasoning. |
||||
* Packages in `pkgs/top-level/python-packages.nix` are sorted quasi-alphabetically to avoid merge conflicts. |
||||
* Python libraries are supposed to be in `python-packages.nix` and packaged with `buildPythonPackage`. Python applications live outside of `python-packages.nix` and are packaged with `buildPythonApplication`. |
@ -1,447 +0,0 @@ |
||||
<section xmlns="http://docbook.org/ns/docbook" |
||||
xmlns:xlink="http://www.w3.org/1999/xlink" |
||||
xml:id="sec-python"> |
||||
|
||||
<title>Python</title> |
||||
|
||||
<para> |
||||
Currently supported interpreters are <varname>python26</varname>, <varname>python27</varname>, |
||||
<varname>python33</varname>, <varname>python34</varname>, <varname>python35</varname> |
||||
and <varname>pypy</varname>. |
||||
</para> |
||||
|
||||
<para> |
||||
<varname>python</varname> is an alias to <varname>python27</varname> and <varname>python3</varname> is an alias to <varname>python34</varname>. |
||||
</para> |
||||
|
||||
<para> |
||||
<varname>python26</varname> and <varname>python27</varname> do not include modules that require |
||||
external dependencies (to reduce dependency bloat). Following modules need to be added as |
||||
<varname>buildInput</varname> explicitly: |
||||
</para> |
||||
|
||||
<itemizedlist> |
||||
<listitem><para><varname>python.modules.bsddb</varname></para></listitem> |
||||
<listitem><para><varname>python.modules.curses</varname></para></listitem> |
||||
<listitem><para><varname>python.modules.curses_panel</varname></para></listitem> |
||||
<listitem><para><varname>python.modules.crypt</varname></para></listitem> |
||||
<listitem><para><varname>python.modules.gdbm</varname></para></listitem> |
||||
<listitem><para><varname>python.modules.sqlite3</varname></para></listitem> |
||||
<listitem><para><varname>python.modules.tkinter</varname></para></listitem> |
||||
<listitem><para><varname>python.modules.readline</varname></para></listitem> |
||||
</itemizedlist> |
||||
|
||||
<para>For convenience <varname>python27Full</varname> and <varname>python26Full</varname> |
||||
are provided with all modules included.</para> |
||||
|
||||
<para> |
||||
Python packages that |
||||
use <link xlink:href="http://pypi.python.org/pypi/setuptools/"><literal>setuptools</literal></link> or <literal>distutils</literal>, |
||||
can be built using the <varname>buildPythonPackage</varname> function as documented below. |
||||
</para> |
||||
|
||||
<para> |
||||
All packages depending on any Python interpreter get appended <varname>$out/${python.sitePackages}</varname> |
||||
to <literal>$PYTHONPATH</literal> if such directory exists. |
||||
</para> |
||||
|
||||
<variablelist> |
||||
<title> |
||||
Useful attributes on interpreters packages: |
||||
</title> |
||||
|
||||
<varlistentry> |
||||
<term><varname>libPrefix</varname></term> |
||||
<listitem><para> |
||||
Name of the folder in <literal>${python}/lib/</literal> for corresponding interpreter. |
||||
</para></listitem> |
||||
</varlistentry> |
||||
|
||||
<varlistentry> |
||||
<term><varname>interpreter</varname></term> |
||||
<listitem><para> |
||||
Alias for <literal>${python}/bin/${executable}.</literal> |
||||
</para></listitem> |
||||
</varlistentry> |
||||
|
||||
<varlistentry> |
||||
<term><varname>buildEnv</varname></term> |
||||
<listitem><para> |
||||
Function to build python interpreter environments with extra packages bundled together. |
||||
See <xref linkend="ssec-python-build-env" /> for usage and documentation. |
||||
</para></listitem> |
||||
</varlistentry> |
||||
|
||||
<varlistentry> |
||||
<term><varname>sitePackages</varname></term> |
||||
<listitem><para> |
||||
Alias for <literal>lib/${libPrefix}/site-packages</literal>. |
||||
</para></listitem> |
||||
</varlistentry> |
||||
|
||||
<varlistentry> |
||||
<term><varname>executable</varname></term> |
||||
<listitem><para> |
||||
Name of the interpreter executable, ie <literal>python3.4</literal>. |
||||
</para></listitem> |
||||
</varlistentry> |
||||
|
||||
</variablelist> |
||||
<section xml:id="ssec-build-python-package"><title><varname>buildPythonPackage</varname> function</title> |
||||
|
||||
<para> |
||||
The function is implemented in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/python-modules/generic/default.nix"> |
||||
<filename>pkgs/development/python-modules/generic/default.nix</filename></link>. |
||||
Example usage: |
||||
|
||||
<programlisting language="nix"> |
||||
twisted = buildPythonPackage { |
||||
name = "twisted-8.1.0"; |
||||
|
||||
src = pkgs.fetchurl { |
||||
url = http://tmrc.mit.edu/mirror/twisted/Twisted/8.1/Twisted-8.1.0.tar.bz2; |
||||
sha256 = "0q25zbr4xzknaghha72mq57kh53qw1bf8csgp63pm9sfi72qhirl"; |
||||
}; |
||||
|
||||
propagatedBuildInputs = [ self.ZopeInterface ]; |
||||
|
||||
meta = { |
||||
homepage = http://twistedmatrix.com/; |
||||
description = "Twisted, an event-driven networking engine written in Python"; |
||||
license = stdenv.lib.licenses.mit; |
||||
}; |
||||
}; |
||||
</programlisting> |
||||
|
||||
Most of Python packages that use <varname>buildPythonPackage</varname> are defined |
||||
in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/python-packages.nix"><filename>pkgs/top-level/python-packages.nix</filename></link> |
||||
and generated for each python interpreter separately into attribute sets <varname>python26Packages</varname>, |
||||
<varname>python27Packages</varname>, <varname>python35Packages</varname>, <varname>python33Packages</varname>, |
||||
<varname>python34Packages</varname> and <varname>pypyPackages</varname>. |
||||
</para> |
||||
|
||||
<para> |
||||
<function>buildPythonPackage</function> mainly does four things: |
||||
|
||||
<orderedlist> |
||||
<listitem><para> |
||||
In the <varname>buildPhase</varname>, it calls |
||||
<literal>${python.interpreter} setup.py bdist_wheel</literal> to build a wheel binary zipfile. |
||||
</para></listitem> |
||||
|
||||
<listitem><para> |
||||
In the <varname>installPhase</varname>, it installs the wheel file using |
||||
<literal>pip install *.whl</literal>. |
||||
</para></listitem> |
||||
|
||||
<listitem><para> |
||||
In the <varname>postFixup</varname> phase, <literal>wrapPythonPrograms</literal> |
||||
bash function is called to wrap all programs in <filename>$out/bin/*</filename> |
||||
directory to include <literal>$PYTHONPATH</literal> and <literal>$PATH</literal> |
||||
environment variables. |
||||
</para></listitem> |
||||
|
||||
<listitem><para> |
||||
In the <varname>installCheck</varname> phase, <literal>${python.interpreter} setup.py test</literal> |
||||
is ran. |
||||
</para></listitem> |
||||
</orderedlist> |
||||
</para> |
||||
|
||||
<para>By default <varname>doCheck = true</varname> is set</para> |
||||
|
||||
<para> |
||||
As in Perl, dependencies on other Python packages can be specified in the |
||||
<varname>buildInputs</varname> and |
||||
<varname>propagatedBuildInputs</varname> attributes. If something is |
||||
exclusively a build-time dependency, use |
||||
<varname>buildInputs</varname>; if it’s (also) a runtime dependency, |
||||
use <varname>propagatedBuildInputs</varname>. |
||||
</para> |
||||
|
||||
<para> |
||||
By default <varname>meta.platforms</varname> is set to the same value |
||||
as the interpreter unless overriden otherwise. |
||||
</para> |
||||
|
||||
<variablelist> |
||||
<title> |
||||
<varname>buildPythonPackage</varname> parameters |
||||
(all parameters from <varname>mkDerivation</varname> function are still supported) |
||||
</title> |
||||
|
||||
<varlistentry> |
||||
<term><varname>namePrefix</varname></term> |
||||
<listitem><para> |
||||
Prepended text to <varname>${name}</varname> parameter. |
||||
Defaults to <literal>"python3.3-"</literal> for Python 3.3, etc. Set it to |
||||
<literal>""</literal> |
||||
if you're packaging an application or a command line tool. |
||||
</para></listitem> |
||||
</varlistentry> |
||||
|
||||
<varlistentry> |
||||
<term><varname>disabled</varname></term> |
||||
<listitem><para> |
||||
If <varname>true</varname>, package is not build for |
||||
particular python interpreter version. Grep around |
||||
<filename>pkgs/top-level/python-packages.nix</filename> |
||||
for examples. |
||||
</para></listitem> |
||||
</varlistentry> |
||||
|
||||
<varlistentry> |
||||
<term><varname>setupPyBuildFlags</varname></term> |
||||
<listitem><para> |
||||
List of flags passed to <command>setup.py build_ext</command> command. |
||||
</para></listitem> |
||||
</varlistentry> |
||||
|
||||
<varlistentry> |
||||
<term><varname>pythonPath</varname></term> |
||||
<listitem><para> |
||||
List of packages to be added into <literal>$PYTHONPATH</literal>. |
||||
Packages in <varname>pythonPath</varname> are not propagated |
||||
(contrary to <varname>propagatedBuildInputs</varname>). |
||||
</para></listitem> |
||||
</varlistentry> |
||||
|
||||
<varlistentry> |
||||
<term><varname>preShellHook</varname></term> |
||||
<listitem><para> |
||||
Hook to execute commands before <varname>shellHook</varname>. |
||||
</para></listitem> |
||||
</varlistentry> |
||||
|
||||
<varlistentry> |
||||
<term><varname>postShellHook</varname></term> |
||||
<listitem><para> |
||||
Hook to execute commands after <varname>shellHook</varname>. |
||||
</para></listitem> |
||||
</varlistentry> |
||||
|
||||
<varlistentry> |
||||
<term><varname>makeWrapperArgs</varname></term> |
||||
<listitem><para> |
||||
A list of strings. Arguments to be passed to |
||||
<varname>makeWrapper</varname>, which wraps generated binaries. By |
||||
default, the arguments to <varname>makeWrapper</varname> set |
||||
<varname>PATH</varname> and <varname>PYTHONPATH</varname> environment |
||||
variables before calling the binary. Additional arguments here can |
||||
allow a developer to set environment variables which will be |
||||
available when the binary is run. For example, |
||||
<varname>makeWrapperArgs = ["--set FOO BAR" "--set BAZ QUX"]</varname>. |
||||
</para></listitem> |
||||
</varlistentry> |
||||
|
||||
</variablelist> |
||||
|
||||
</section> |
||||
|
||||
<section xml:id="ssec-python-build-env"><title><function>python.buildEnv</function> function</title> |
||||
<para> |
||||
Create Python environments using low-level <function>pkgs.buildEnv</function> function. Example <filename>default.nix</filename>: |
||||
|
||||
<programlisting language="nix"> |
||||
<![CDATA[with import <nixpkgs> {}; |
||||
|
||||
python.buildEnv.override { |
||||
extraLibs = [ pkgs.pythonPackages.pyramid ]; |
||||
ignoreCollisions = true; |
||||
}]]> |
||||
</programlisting> |
||||
|
||||
Running <command>nix-build</command> will create |
||||
<filename>/nix/store/cf1xhjwzmdki7fasgr4kz6di72ykicl5-python-2.7.8-env</filename> |
||||
with wrapped binaries in <filename>bin/</filename>. |
||||
</para> |
||||
|
||||
<para> |
||||
You can also use <varname>env</varname> attribute to create local |
||||
environments with needed packages installed (somewhat comparable to |
||||
<literal>virtualenv</literal>). For example, with the following |
||||
<filename>shell.nix</filename>: |
||||
|
||||
<programlisting language="nix"> |
||||
<![CDATA[with import <nixpkgs> {}; |
||||
|
||||
(python3.buildEnv.override { |
||||
extraLibs = with python3Packages; |
||||
[ numpy |
||||
requests |
||||
]; |
||||
}).env]]> |
||||
</programlisting> |
||||
|
||||
Running <command>nix-shell</command> will drop you into a shell where |
||||
<command>python</command> will have specified packages in its path. |
||||
</para> |
||||
|
||||
<variablelist> |
||||
<title> |
||||
<function>python.buildEnv</function> arguments |
||||
</title> |
||||
|
||||
<varlistentry> |
||||
<term><varname>extraLibs</varname></term> |
||||
<listitem><para> |
||||
List of packages installed inside the environment. |
||||
</para></listitem> |
||||
</varlistentry> |
||||
|
||||
<varlistentry> |
||||
<term><varname>postBuild</varname></term> |
||||
<listitem><para> |
||||
Shell command executed after the build of environment. |
||||
</para></listitem> |
||||
</varlistentry> |
||||
|
||||
<varlistentry> |
||||
<term><varname>ignoreCollisions</varname></term> |
||||
<listitem><para> |
||||
Ignore file collisions inside the environment (default is <varname>false</varname>). |
||||
</para></listitem> |
||||
</varlistentry> |
||||
</variablelist> |
||||
</section> |
||||
|
||||
<section xml:id="ssec-python-tools"><title>Tools</title> |
||||
|
||||
<para>Packages inside nixpkgs are written by hand. However many tools |
||||
exist in community to help save time. No tool is preferred at the moment. |
||||
</para> |
||||
|
||||
<itemizedlist> |
||||
|
||||
<listitem><para> |
||||
<link xlink:href="https://github.com/proger/python2nix">python2nix</link> |
||||
by Vladimir Kirillov |
||||
</para></listitem> |
||||
|
||||
<listitem><para> |
||||
<link xlink:href="https://github.com/garbas/pypi2nix">pypi2nix</link> |
||||
by Rok Garbas |
||||
</para></listitem> |
||||
|
||||
<listitem><para> |
||||
<link xlink:href="https://github.com/offlinehacker/pypi2nix">pypi2nix</link> |
||||
by Jaka Hudoklin |
||||
</para></listitem> |
||||
|
||||
</itemizedlist> |
||||
|
||||
</section> |
||||
|
||||
<section xml:id="ssec-python-development"><title>Development</title> |
||||
|
||||
<para> |
||||
To develop Python packages <function>buildPythonPackage</function> has |
||||
additional logic inside <varname>shellPhase</varname> to run |
||||
<command>pip install -e . --prefix $TMPDIR/</command> for the package. |
||||
</para> |
||||
|
||||
<warning><para><varname>shellPhase</varname> is executed only if <filename>setup.py</filename> |
||||
exists.</para></warning> |
||||
|
||||
<para> |
||||
Given a <filename>default.nix</filename>: |
||||
|
||||
<programlisting language="nix"> |
||||
<![CDATA[with import <nixpkgs> {}; |
||||
|
||||
buildPythonPackage { |
||||
name = "myproject"; |
||||
|
||||
buildInputs = with pkgs.pythonPackages; [ pyramid ]; |
||||
|
||||
src = ./.; |
||||
}]]> |
||||
</programlisting> |
||||
|
||||
Running <command>nix-shell</command> with no arguments should give you |
||||
the environment in which the package would be build with |
||||
<command>nix-build</command>. |
||||
</para> |
||||
|
||||
<para> |
||||
Shortcut to setup environments with C headers/libraries and python packages: |
||||
|
||||
<programlisting language="bash">$ nix-shell -p pythonPackages.pyramid zlib libjpeg git</programlisting> |
||||
</para> |
||||
|
||||
<note><para> |
||||
There is a boolean value <varname>lib.inNixShell</varname> set to |
||||
<varname>true</varname> if nix-shell is invoked. |
||||
</para></note> |
||||
|
||||
</section> |
||||
|
||||
<section xml:id="ssec-python-faq"><title>FAQ</title> |
||||
|
||||
<variablelist> |
||||
|
||||
<varlistentry> |
||||
<term>How to solve circular dependencies?</term> |
||||
<listitem><para> |
||||
If you have packages <varname>A</varname> and <varname>B</varname> that |
||||
depend on each other, when packaging <varname>B</varname> override package |
||||
<varname>A</varname> not to depend on <varname>B</varname> as input |
||||
(and also the other way around). |
||||
</para></listitem> |
||||
</varlistentry> |
||||
|
||||
<varlistentry> |
||||
<term><varname>install_data / data_files</varname> problems resulting into <literal>error: could not create '/nix/store/6l1bvljpy8gazlsw2aw9skwwp4pmvyxw-python-2.7.8/etc': Permission denied</literal></term> |
||||
<listitem><para> |
||||
<link xlink:href="https://bitbucket.org/pypa/setuptools/issue/130/install_data-doesnt-respect-prefix"> |
||||
Known bug in setuptools <varname>install_data</varname> does not respect --prefix</link>. Example of |
||||
such package using the feature is <filename>pkgs/tools/X11/xpra/default.nix</filename>. As workaround |
||||
install it as an extra <varname>preInstall</varname> step: |
||||
|
||||
<programlisting>${python.interpreter} setup.py install_data --install-dir=$out --root=$out |
||||
sed -i '/ = data_files/d' setup.py</programlisting> |
||||
</para></listitem> |
||||
</varlistentry> |
||||
|
||||
<varlistentry> |
||||
<term>Rationale of non-existent global site-packages</term> |
||||
<listitem><para> |
||||
There is no need to have global site-packages in Nix. Each package has isolated |
||||
dependency tree and installing any python package will only populate <varname>$PATH</varname> |
||||
inside user environment. See <xref linkend="ssec-python-build-env" /> to create self-contained |
||||
interpreter with a set of packages. |
||||
</para></listitem> |
||||
</varlistentry> |
||||
|
||||
</variablelist> |
||||
|
||||
</section> |
||||
|
||||
|
||||
<section xml:id="ssec-python-contrib"><title>Contributing guidelines</title> |
||||
<para> |
||||
Following rules are desired to be respected: |
||||
</para> |
||||
|
||||
<itemizedlist> |
||||
|
||||
<listitem><para> |
||||
Make sure package builds for all python interpreters. Use <varname>disabled</varname> argument to |
||||
<function>buildPythonPackage</function> to set unsupported interpreters. |
||||
</para></listitem> |
||||
|
||||
<listitem><para> |
||||
If tests need to be disabled for a package, make sure you leave a comment about reasoning. |
||||
</para></listitem> |
||||
|
||||
<listitem><para> |
||||
Packages in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/python-packages.nix"><filename>pkgs/top-level/python-packages.nix</filename></link> |
||||
are sorted quasi-alphabetically to avoid merge conflicts. |
||||
</para></listitem> |
||||
|
||||
</itemizedlist> |
||||
|
||||
</section> |
||||
|
||||
</section> |
||||
|
Loading…
Reference in new issue