From 07b6d3d2c6f8833d01ebfc2706afa50347078ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Domen=20Ko=C5=BEar?= Date: Sat, 8 Nov 2014 21:59:57 +0100 Subject: [PATCH] Initial documentation for Python packaging. Feedback welcome. cc @chaoflow @offlinehacker @garbas @goodwillcoding @brodul @cillianderoiste @matejc Fixes #64 --- doc/language-support.xml | 443 ++++++++++++++++++++++++++++++++++++--- doc/stdenv.xml | 7 +- 2 files changed, 413 insertions(+), 37 deletions(-) diff --git a/doc/language-support.xml b/doc/language-support.xml index 5e49121e695b..67949808ec06 100644 --- a/doc/language-support.xml +++ b/doc/language-support.xml @@ -108,7 +108,7 @@ a preConfigure hook to generate a configuration file used by Makefile.PL: -{buildPerlPackage, fetchurl, db}: +{ buildPerlPackage, fetchurl, db }: buildPerlPackage rec { name = "BerkeleyDB-0.36"; @@ -191,45 +191,424 @@ you need it. -
Python +
Python + + + Currently supported interpreters are python26, python27, + python32, python33, python34 + and pypy. + + + + python is an alias of python27 and python3 is an alias of python34. + + + + python26 and python27 do not include modules that require + external dependencies (to reduce dependency bloat). 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. Python packages that - use setuptools, - which many Python packages do nowadays, can be built very simply using - the buildPythonPackage function. This function is - implemented - in pkgs/development/python-modules/generic/default.nix - and works similarly to buildPerlPackage. (See - for details.) + use setuptools or distutils, + can be built using the buildPythonPackage function as documented below. - Python packages that use buildPythonPackage are - defined - in pkgs/top-level/python-packages.nix. - Most of them are simple. For example: - - -twisted = buildPythonPackage { - name = "twisted-8.1.0"; - - src = fetchurl { - url = http://tmrc.mit.edu/mirror/twisted/Twisted/8.1/Twisted-8.1.0.tar.bz2; - sha256 = "0q25zbr4xzknaghha72mq57kh53qw1bf8csgp63pm9sfi72qhirl"; - }; - - propagatedBuildInputs = [ pkgs.ZopeInterface ]; - - meta = { - homepage = http://twistedmatrix.com/; - description = "Twisted, an event-driven networking engine written in Python"; - license = "MIT"; - }; -}; - + All packages depending on any Python interpreter get appended $out/${python.libPrefix}/site-packages + to $PYTHONPATH if such directory exists. + + + Useful attributes on interpreters packages: + + + + 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 for usage and documentation. + + + + + sitePackages + + Alias for lib/${libPrefix}/site-packages. + + + + + executable + + Name of the interpreter executable, ie python3.4. + + + + +
<varname>buildPythonPackage</varname> function + + + The function is implemented in + pkgs/development/python-modules/generic/default.nix. + Example usage: + + + 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; + }; + }; + + + Most of Python packages that use buildPythonPackage are defined + in pkgs/top-level/python-packages.nix + and generated for each python interpreter separately into attribute sets python26Packages, + python27Packages, python32Packages, python33Packages, + python34Packages and pypyPackages. + + + + buildPythonPackage mainly does four things: + + + + In the configurePhase, it patches + setup.py to always include setuptools before + distutils for monkeypatching machinery to take place. + + + + In the buildPhase, it calls + ${python.interpreter} setup.py build ... + + + + In the installPhase, it calls + ${python.interpreter} setup.py install ... + + + + In the postFixup phase, wrapPythonPrograms + bash function is called to wrap all programs in $out/bin/* + directory to include $PYTHONPATH and $PATH + environment variables. + + + + + By default doCheck = true is set and tests are run with + ${python.interpreter} setup.py test command in checkPhase. + + propagatedBuildInputs packages are propagated to user environment. + + + By default meta.platforms is set to the same value + as the interpreter unless overriden otherwise. + + + + + <varname>buildPythonPackage</varname> parameters + (all parameters from <varname>mkDerivation</varname> 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. + + + + + setupPyInstallFlags + + List of flags passed to setup.py install command. + + + + + setupPyBuildFlags + + List of flags passed to setup.py build command. + + + + + pythonPath + + List of packages to be added into $PYTHONPATH. + Packages in pythonPath are not propagated into user environment + (contrary to propagatedBuildInputs). + + + + + preShellHook + + Hook to execute commands before shellHook. + + + + + postShellHook + + Hook to execute commands after shellHook. + + + + + distutilsExtraCfg + + Extra lines passed to [easy_install] section of + distutils.cfg (acts as global setup.cfg + configuration). + + + + + +
+ +
<function>python.buildEnv</function> function + + Create Python envorinments using low-level pkgs.buildEnv function. Example default.nix: + + + {}; + + python.buildEnv.override { + extraLibs = [ pkgs.pythonPackages.pyramid ]; + ignoreCollisions = true; + } + ]]> + + + Running nix-build will create + /nix/store/cf1xhjwzmdki7fasgr4kz6di72ykicl5-python-2.7.8-env + with wrapped binaries in bin/. + + + + + <function>python.buildEnv</function> 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). + + + +
+ +
Tools + +Packages inside nixpkgs are written by hand. However many tools +exist in community to help save time. No tool is prefered at the moment. + + + + + + python2nix + by Vladimir Kirillov + + + + pypi2nix + by Rok Garbas + + + + pypi2nix + by Jaka Hudoklin + + + + +
+ +
Development + + + To develop Python packages bulidPythonPackage has + additional logic inside shellPhase to run + ${python.interpreter} setup.py develop for the package. + + + + Given a default.nix: + + + {}; + + 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. + + +
+ +
FAQ + + + + + How to solve circular dependencies? + + If you have packages A and B that + depend on each other, when packaging B override package + A not to depend on B as input + (and also the other way around). + + + + + install_data / data_files problems resulting into error: could not create '/nix/store/6l1bvljpy8gazlsw2aw9skwwp4pmvyxw-python-2.7.8/etc': Permission denied + + + Known bug in setuptools install_data does not respect --prefix. 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 + + 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 $PATH + inside user environment. See to create self-contained + interpreter with a set of packages. + + + + + +
+ + +
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. + + + + +
+
diff --git a/doc/stdenv.xml b/doc/stdenv.xml index 8c6266b2672a..00fa7567c078 100644 --- a/doc/stdenv.xml +++ b/doc/stdenv.xml @@ -1120,12 +1120,9 @@ echo @foo@ Python Adds the - lib/python2.5/site-packages subdirectory of + lib/${python.libPrefix}/site-packages subdirectory of each build input to the PYTHONPATH environment - variable. - - This should be generalised: the Python version - shouldn’t be hard-coded. + variable.