about summary refs log tree commit diff
path: root/doc/languages-frameworks/python.md
diff options
context:
space:
mode:
Diffstat (limited to 'doc/languages-frameworks/python.md')
-rw-r--r--doc/languages-frameworks/python.md382
1 files changed, 226 insertions, 156 deletions
diff --git a/doc/languages-frameworks/python.md b/doc/languages-frameworks/python.md
index 3f5d500620bb..d9306ae56bd5 100644
--- a/doc/languages-frameworks/python.md
+++ b/doc/languages-frameworks/python.md
@@ -3,7 +3,7 @@
 ## User Guide
 
 Several versions of Python are available on Nix as well as a high amount of
-packages. The default interpreter is CPython 3.5.
+packages. The default interpreter is CPython 2.7.
 
 ### Using Python
 
@@ -74,7 +74,6 @@ 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> {};
 
@@ -101,22 +100,25 @@ On Nix all packages are built by functions. The main function in Nix for buildin
 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 = "mirror://pypi/t/toolz/toolz-${version}.tar.gz";
-    sha256 = "43c2c9e5e7a16b6c88ba3088a9bfc82f7db8e13378be7c78d6c14a5f8ed05afd";
-  };
+  toolz = buildPythonPackage rec {
+    name = "toolz-${version}";
+    version = "0.7.4";
 
-  meta = {
-    homepage = "http://github.com/pytoolz/toolz/";
-    description = "List processing tools and functional utilities";
-    license = licenses.bsd3;
-    maintainers = with maintainers; [ fridh ];
+    src = pkgs.fetchurl {
+      url = "mirror://pypi/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
@@ -129,7 +131,7 @@ specify some (optional) [meta information](http://nixos.org/nixpkgs/manual/#chap
 
 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`.
+so e.g. `python27Packages`, `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,
@@ -143,7 +145,7 @@ pkgs.python35Packages.buildPythonPackage rec {
   name = "toolz-${version}";
   version = "0.8.0";
 
-  src = pkgs.fetchurl{
+  src = pkgs.fetchurl {
     url = "mirror://pypi/t/toolz/toolz-${version}.tar.gz";
     sha256 = "e8451af61face57b7c5d09e71c0d27b8005f001ead56e9fdf470417e5cc6d479";
   };
@@ -174,7 +176,7 @@ with import <nixpkgs> {};
       name = "toolz-${version}";
       version = "0.8.0";
 
-      src = pkgs.fetchurl{
+      src = pkgs.fetchurl {
         url = "mirror://pypi/t/toolz/toolz-${version}.tar.gz";
         sha256 = "e8451af61face57b7c5d09e71c0d27b8005f001ead56e9fdf470417e5cc6d479";
       };
@@ -215,25 +217,28 @@ 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 = "mirror://pypi/D/DataShape/${name}.tar.gz";
-    sha256 = "14b2ef766d4c9652ab813182e866f493475e65e558bed0822e38bf07bba1a278";
-  };
+  datashape = buildPythonPackage rec {
+    name = "datashape-${version}";
+    version = "0.4.7";
 
-  buildInputs = with self; [ pytest ];
-  propagatedBuildInputs = with self; [ numpy multipledispatch dateutil ];
+    src = pkgs.fetchurl {
+      url = "mirror://pypi/D/DataShape/${name}.tar.gz";
+      sha256 = "14b2ef766d4c9652ab813182e866f493475e65e558bed0822e38bf07bba1a278";
+    };
 
-  meta = {
-    homepage = https://github.com/ContinuumIO/datashape;
-    description = "A data description language";
-    license = licenses.bsd2;
-    maintainers = with maintainers; [ fridh ];
+    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
@@ -247,23 +252,26 @@ 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 = "mirror://pypi/l/lxml/${name}.tar.gz";
-    sha256 = "16a0fa97hym9ysdk3rmqz32xdjqmy4w34ld3rm3jf5viqjx65lxk";
-  };
+  lxml = buildPythonPackage rec {
+    name = "lxml-3.4.4";
 
-  buildInputs = with self; [ pkgs.libxml2 pkgs.libxslt ];
+    src = pkgs.fetchurl {
+      url = "mirror://pypi/l/lxml/${name}.tar.gz";
+      sha256 = "16a0fa97hym9ysdk3rmqz32xdjqmy4w34ld3rm3jf5viqjx65lxk";
+    };
 
-  meta = {
-    description = "Pythonic binding for the libxml2 and libxslt libraries";
-    homepage = http://lxml.de;
-    license = licenses.bsd3;
-    maintainers = with maintainers; [ sjourdois ];
+    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
@@ -277,33 +285,37 @@ 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 = "mirror://pypi/p/pyFFTW/pyFFTW-${version}.tar.gz";
-    sha256 = "f6bbb6afa93085409ab24885a1a3cdb8909f095a142f4d49e346f2bd1b789074";
-  };
+  pyfftw = buildPythonPackage rec {
+    name = "pyfftw-${version}";
+    version = "0.9.2";
 
-  buildInputs = [ pkgs.fftw pkgs.fftwFloat pkgs.fftwLongDouble];
+    src = pkgs.fetchurl {
+      url = "mirror://pypi/p/pyFFTW/pyFFTW-${version}.tar.gz";
+      sha256 = "f6bbb6afa93085409ab24885a1a3cdb8909f095a142f4d49e346f2bd1b789074";
+    };
 
-  propagatedBuildInputs = with self; [ numpy scipy ];
+    buildInputs = [ pkgs.fftw pkgs.fftwFloat pkgs.fftwLongDouble];
 
-  # Tests cannot import pyfftw. pyfftw works fine though.
-  doCheck = false;
+    propagatedBuildInputs = with self; [ numpy scipy ];
 
-  LDFLAGS="-L${pkgs.fftw.dev}/lib -L${pkgs.fftwFloat.out}/lib -L${pkgs.fftwLongDouble.out}/lib"
-  CFLAGS="-I${pkgs.fftw.dev}/include -I${pkgs.fftwFloat.dev}/include -I${pkgs.fftwLongDouble.dev}/include"
-  '';
+    # Tests cannot import pyfftw. pyfftw works fine though.
+    doCheck = false;
 
-  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 ];
+    preConfigure = ''
+      export LDFLAGS="-L${pkgs.fftw.dev}/lib -L${pkgs.fftwFloat.out}/lib -L${pkgs.fftwLongDouble.out}/lib"
+      export CFLAGS="-I${pkgs.fftw.dev}/include -I${pkgs.fftwFloat.dev}/include -I${pkgs.fftwLongDouble.dev}/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.
 
@@ -316,10 +328,7 @@ That way, you can run updated code without having to reinstall after each and ev
 Development mode is also available. 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;
-```
+`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
@@ -338,7 +347,7 @@ 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.
@@ -371,7 +380,7 @@ buildPythonPackage rec {
   name = "toolz-${version}";
   version = "0.7.4";
 
-  src = pkgs.fetchurl{
+  src = pkgs.fetchurl {
     url = "mirror://pypi/t/toolz/toolz-${version}.tar.gz";
     sha256 = "43c2c9e5e7a16b6c88ba3088a9bfc82f7db8e13378be7c78d6c14a5f8ed05afd";
   };
@@ -382,7 +391,7 @@ buildPythonPackage rec {
     license = licenses.bsd3;
     maintainers = with maintainers; [ fridh ];
   };
-};
+}
 ```
 
 It takes two arguments, `pkgs` and `buildPythonPackage`.
@@ -392,7 +401,10 @@ We now call this function using `callPackage` in the definition of our environme
 with import <nixpkgs> {};
 
 ( let
-    toolz = pkgs.callPackage ~/path/to/toolz/release.nix { pkgs=pkgs; buildPythonPackage=pkgs.python35Packages.buildPythonPackage; };
+    toolz = pkgs.callPackage /path/to/toolz/release.nix {
+      pkgs = pkgs;
+      buildPythonPackage = pkgs.python35Packages.buildPythonPackage;
+    };
   in pkgs.python35.withPackages (ps: [ ps.numpy toolz ])
 ).env
 ```
@@ -410,8 +422,8 @@ and in this case the `python35` interpreter is automatically used.
 
 ### Interpreters
 
-Versions 2.6, 2.7, 3.3, 3.4 and 3.5 of the CPython interpreter are available as respectively
-`python26`, `python27`, `python33`, `python34` and `python35`. The PyPy interpreter
+Versions 2.7, 3.3, 3.4, 3.5 and 3.6 of the CPython interpreter are available as
+respectively `python27`, `python33`, `python34`, `python35` and `python36`. The PyPy interpreter
 is available as `pypy`. The aliases `python2` and `python3` correspond to respectively `python27` and
 `python35`. The default interpreter, `python`, maps to `python2`.
 The Nix expressions for the interpreters can be found in
@@ -460,6 +472,7 @@ sets are
 * `pkgs.python33Packages`
 * `pkgs.python34Packages`
 * `pkgs.python35Packages`
+* `pkgs.python36Packages`
 * `pkgs.pypyPackages`
 
 and the aliases
@@ -474,22 +487,27 @@ The `buildPythonPackage` function is implemented in
 `pkgs/development/interpreters/python/build-python-package.nix`
 
 The following is an example:
+```nix
+{ # ...
 
-    twisted = buildPythonPackage {
-      name = "twisted-8.1.0";
+  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";
-      };
+    src = pkgs.fetchurl {
+      url = http://tmrc.mit.edu/mirror/twisted/Twisted/8.1/Twisted-8.1.0.tar.bz2;
+      sha256 = "0q25zbr4xzknaghha72mq57kh53qw1bf8csgp63pm9sfi72qhirl";
+    };
 
-      propagatedBuildInputs = [ self.ZopeInterface ];
+    propagatedBuildInputs = [ self.ZopeInterface ];
 
-      meta = {
-        homepage = http://twistedmatrix.com/;
-        description = "Twisted, an event-driven networking engine written in Python";
-        license = stdenv.lib.licenses.mit; };
-      };
+    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:
 
@@ -539,29 +557,32 @@ Because with an application we're not interested in multiple version the prefix
 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`
+```nix
+with import <nixpkgs> {};
 
-    with import <nixpkgs> {};
-
-    python.buildEnv.override {
-      extraLibs = [ pkgs.pythonPackages.pyramid ];
-      ignoreCollisions = true;
-    }
+python.buildEnv.override {
+  extraLibs = [ pkgs.pythonPackages.pyramid ];
+  ignoreCollisions = true;
+}
+```
 
 and running `nix-build` will create
-
-    /nix/store/cf1xhjwzmdki7fasgr4kz6di72ykicl5-python-2.7.8-env
+```
+/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`
+```nix
+with import <nixpkgs> {};
 
-    with import <nixpkgs> {};
-
-    (python3.buildEnv.override {
-      extraLibs = with python3Packages; [ numpy requests2 ];
-    }).env
+(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.
@@ -576,34 +597,40 @@ specified packages in its path.
 #### python.withPackages function
 
 The `python.withPackages` function provides a simpler interface to the `python.buildEnv` functionality.
-It takes a function as an argument that is passed the set of python packages and returns the list 
+It takes a function as an argument that is passed the set of python packages and returns the list
 of the packages to be included in the environment. Using the `withPackages` function, the previous
 example for the Pyramid Web Framework environment can be written like this:
+```nix
+with import <nixpkgs> {};
 
-    with import <nixpkgs> {};
-
-    python.withPackages (ps: [ps.pyramid])
+python.withPackages (ps: [ps.pyramid])
+```
 
-`withPackages` passes the correct package set for the specific interpreter version as an 
+`withPackages` passes the correct package set for the specific interpreter version as an
 argument to the function. In the above example, `ps` equals `pythonPackages`.
 But you can also easily switch to using python3:
-    
-    with import <nixpkgs> {};
+```nix
+with import <nixpkgs> {};
 
-    python3.withPackages (ps: [ps.pyramid])
+python3.withPackages (ps: [ps.pyramid])
+```
 
 Now, `ps` is set to `python3Packages`, matching the version of the interpreter.
 
 As `python.withPackages` simply uses `python.buildEnv` under the hood, it also supports the `env`
 attribute. The `shell.nix` file from the previous section can thus be also written like this:
+```nix
+with import <nixpkgs> {};
 
-    with import <nixpkgs> {};
-
-    (python33.withPackages (ps: [ps.numpy ps.requests2])).env
+(python33.withPackages (ps: [ps.numpy ps.requests])).env
+```
 
 In contrast to `python.buildEnv`, `python.withPackages` does not support the more advanced options
 such as `ignoreCollisions = true` or `postBuild`. If you need them, you have to use `python.buildEnv`.
 
+Python 2 namespace packages may provide `__init__.py` that collide. In that case `python.buildEnv` 
+should be used with `ignoreCollisions = true`.
+
 ### Development mode
 
 Development or editable mode is supported. To develop Python packages
@@ -613,22 +640,24 @@ install -e . --prefix $TMPDIR/`for the package.
 Warning: `shellPhase` is executed only if `setup.py` exists.
 
 Given a `default.nix`:
+```nix
+with import <nixpkgs> {};
 
-    with import <nixpkgs> {};
-
-    buildPythonPackage { name = "myproject";
+buildPythonPackage { name = "myproject";
 
-    buildInputs = with pkgs.pythonPackages; [ pyramid ];
+buildInputs = with pkgs.pythonPackages; [ pyramid ];
 
-    src = ./.; }
+src = ./.; }
+```
 
 Running `nix-shell` with no arguments should give you
 the environment in which the package would be built with
 `nix-build`.
 
 Shortcut to setup environments with C headers/libraries and python packages:
-
-    $ nix-shell -p pythonPackages.pyramid zlib libjpeg git
+```shell
+nix-shell -p pythonPackages.pyramid zlib libjpeg git
+```
 
 Note: There is a boolean value `lib.inNixShell` set to `true` if nix-shell is invoked.
 
@@ -641,6 +670,19 @@ community to help save time. No tool is preferred at the moment.
 - [pypi2nix](https://github.com/garbas/pypi2nix) by Rok Garbas
 - [pypi2nix](https://github.com/offlinehacker/pypi2nix) by Jaka Hudoklin
 
+### Deterministic builds
+
+Python 2.7, 3.5 and 3.6 are now built deterministically and 3.4 mostly.
+Minor modifications had to be made to the interpreters in order to generate
+deterministic bytecode. This has security implications and is relevant for
+those using Python in a `nix-shell`.
+
+When the environment variable `DETERMINISTIC_BUILD` is set, all bytecode will have timestamp 1.
+The `buildPythonPackage` function sets `DETERMINISTIC_BUILD=1` and
+[PYTHONHASHSEED=0](https://docs.python.org/3.5/using/cmdline.html#envvar-PYTHONHASHSEED).
+Both are also exported in `nix-shell`.
+
+
 ## FAQ
 
 ### How can I install a working Python environment?
@@ -663,7 +705,7 @@ with import <nixpkgs> {};
 pkgs.python35.withPackages (ps: with ps; [ numpy ipython ])
 ```
 and install it in your profile with
-```
+```shell
 nix-env -if build.nix
 ```
 Now you can use the Python interpreter, as well as the extra packages that you added to the environment.
@@ -671,15 +713,19 @@ Now you can use the Python interpreter, as well as the extra packages that you a
 #### Environment defined in `~/.nixpkgs/config.nix`
 
 If you prefer to, you could also add the environment as a package override to the Nixpkgs set.
-```
+```nix
+{ # ...
+
   packageOverrides = pkgs: with pkgs; {
     myEnv = python35.withPackages (ps: with ps; [ numpy ipython ]);
   };
+}
 ```
 and install it in your profile with
-```
+```shell
 nix-env -iA nixpkgs.myEnv
 ```
+
 We're installing using the attribute path and assume the channels is named `nixpkgs`.
 Note that I'm using the attribute path here.
 
@@ -688,9 +734,12 @@ Note that I'm using the attribute path here.
 For the sake of completeness, here's another example how to install the environment system-wide.
 
 ```nix
-environment.systemPackages = with pkgs; [
-  (python35.withPackages(ps: with ps; [ numpy ipython ]))
-];
+{ # ...
+
+  environment.systemPackages = with pkgs; [
+    (python35.withPackages(ps: with ps; [ numpy ipython ]))
+  ];
+}
 ```
 
 ### How to solve circular dependencies?
@@ -727,19 +776,18 @@ All packages in the Python package set will now use the updated `scipy` version.
 ```nix
 with import <nixpkgs> {};
 
-(
-let
-  packageOverrides = self: super: {
-    scipy = super.scipy_0_17;
-  };
-in (pkgs.python35.override {inherit packageOverrides;}).withPackages (ps: [ps.blaze])
+( let
+    packageOverrides = self: super: {
+      scipy = super.scipy_0_17;
+    };
+  in (pkgs.python35.override {inherit packageOverrides;}).withPackages (ps: [ps.blaze])
 ).env
 ```
 The requested package `blaze` depends on `pandas` which itself depends on `scipy`.
 
 If you want the whole of Nixpkgs to use your modifications, then you can use `overlays`
 as explained in this manual. In the following example we build a `inkscape` using a different version of `numpy`.
-```
+```nix
 let
   pkgs = import <nixpkgs> {};
   newpkgs = import pkgs.path { overlays = [ (pkgsself: pkgssuper: {
@@ -762,32 +810,32 @@ This is because files are included that depend on items in the Nix store which h
 The command `bdist_wheel` takes into account `SOURCE_DATE_EPOCH`, and `nix-shell` sets this to 1. By setting it to a value corresponding to 1980 or later, or by unsetting it, it is possible to build wheels.
 
 Use 1980 as timestamp:
-```
+```shell
 nix-shell --run "SOURCE_DATE_EPOCH=315532800 python3 setup.py bdist_wheel"
 ```
 or the current time:
-```
+```shell
 nix-shell --run "SOURCE_DATE_EPOCH=$(date +%s) python3 setup.py bdist_wheel"
 ```
 or unset:
-```
+```shell
 nix-shell --run "unset SOURCE_DATE_EPOCH; python3 setup.py bdist_wheel"
 ```
 
 ### `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.
+```
+could not create '/nix/store/6l1bvljpy8gazlsw2aw9skwwp4pmvyxw-python-2.7.8/etc':
+Permission denied
+```
+This is a [known bug](https://github.com/pypa/setuptools/issues/130) 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
-
+```shell
+${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
 
@@ -811,11 +859,11 @@ and install python modules through `pip` the traditional way.
 
 Create this `default.nix` file, together with a `requirements.txt` and simply execute `nix-shell`.
 
-```
+```nix
 with import <nixpkgs> {};
 with pkgs.python27Packages;
 
-stdenv.mkDerivation { 
+stdenv.mkDerivation {
   name = "impurePythonEnv";
   buildInputs = [
     # these packages are required for virtualenv and pip to work:
@@ -823,10 +871,10 @@ stdenv.mkDerivation {
     python27Full
     python27Packages.virtualenv
     python27Packages.pip
-    # the following packages are related to the dependencies of your python 
-    # project. 
-    # In this particular example the python modules listed in the 
-    # requirements.tx require the following packages to be installed locally 
+    # the following packages are related to the dependencies of your python
+    # project.
+    # In this particular example the python modules listed in the
+    # requirements.tx require the following packages to be installed locally
     # in order to compile any binary extensions they may require.
     #
     taglib
@@ -841,7 +889,7 @@ stdenv.mkDerivation {
   shellHook = ''
   # set SOURCE_DATE_EPOCH so that we can use python wheels
   SOURCE_DATE_EPOCH=$(date +%s)
-  virtualenv --no-setuptools venv 
+  virtualenv --no-setuptools venv
   export PATH=$PWD/venv/bin:$PATH
   pip install -r requirements.txt
   '';
@@ -849,10 +897,31 @@ stdenv.mkDerivation {
 ```
 
 Note that the `pip install` is an imperative action. So every time `nix-shell`
-is executed it will attempt to download the python modules listed in 
+is executed it will attempt to download the python modules listed in
 requirements.txt. However these will be cached locally within the `virtualenv`
 folder and not downloaded again.
 
+### How to override a Python package from `configuration.nix`?
+
+If you need to change a package's attribute(s) from `configuration.nix` you could do:
+
+```nix
+  nixpkgs.config.packageOverrides = superP: {
+    pythonPackages = superP.pythonPackages.override {
+      overrides = self: super: {
+        bepasty-server = super.bepasty-server.overrideAttrs ( oldAttrs: {
+          src = pkgs.fetchgit {
+            url = "https://github.com/bepasty/bepasty-server";
+            sha256 = "9ziqshmsf0rjvdhhca55sm0x8jz76fsf2q4rwh4m6lpcf8wr0nps";
+            rev = "e2516e8cf4f2afb5185337073607eb9e84a61d2d";
+          };
+        });
+      };
+    };
+  };
+```
+
+If you are using the `bepasty-server` package somewhere, for example in `systemPackages` or indirectly from `services.bepasty`, then a `nixos-rebuild switch` will rebuild the system but with the `bepasty-server` package using a different `src` attribute. This way one can modify `python` based software/libraries easily. Using `self` and `super` one can also alter dependencies (`buildInputs`) between the old state (`self`) and new state (`super`). 
 
 ## Contributing
 
@@ -860,7 +929,8 @@ folder and not downloaded again.
 
 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`.
+* Python libraries are supposed to be called from `python-packages.nix` and packaged with `buildPythonPackage`. The expression of a library should be in `pkgs/development/python-modules/<name>/default.nix`. Libraries in `pkgs/top-level/python-packages.nix` are sorted quasi-alphabetically to avoid merge conflicts.
+* Python applications live outside of `python-packages.nix` and are packaged with `buildPythonApplication`.
+* Make sure libraries build for all Python interpreters.
+* By default we enable tests. Make sure the tests are found and, in the case of libraries, are passing for all interpreters. If certain tests fail they can be disabled individually. Try to avoid disabling the tests altogether. In any case, when you disable tests, leave a comment explaining why.
+* Commit names of Python libraries should include `pythonPackages`, for example `pythonPackages.numpy: 1.11 -> 1.12`.