about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNikolay Amiantov <ab@fmap.me>2016-08-15 12:35:32 +0300
committerNikolay Amiantov <ab@fmap.me>2016-08-20 00:42:49 +0300
commit01624e1ac29ee0854cb63d0c1efb6d791c1441d4 (patch)
tree7eadb8facde772c78c284d6ea35683fab7580e48
parentedb9416228a1c1087313ef52da375f8dd36c6ea4 (diff)
wrapPythonProgram: use site.addsitedir instead of PYTHONPATH
-rw-r--r--doc/languages-frameworks/python.md7
-rw-r--r--pkgs/development/python-modules/generic/wrap.sh2
-rw-r--r--pkgs/top-level/python-packages.nix14
3 files changed, 19 insertions, 4 deletions
diff --git a/doc/languages-frameworks/python.md b/doc/languages-frameworks/python.md
index 434a9b156e787..89659c2166b15 100644
--- a/doc/languages-frameworks/python.md
+++ b/doc/languages-frameworks/python.md
@@ -503,9 +503,12 @@ and can be used as:
 
 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 `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 `postFixup` phase, the `wrapPythonPrograms` bash function is called to
+  wrap all programs in the `$out/bin/*` directory to include `$PATH`
+  environment variable and add dependent libraries to script's `sys.path`.
 * In the `installCheck` phase, `${python.interpreter} setup.py test` is ran.
 
 As in Perl, dependencies on other Python packages can be specified in the
diff --git a/pkgs/development/python-modules/generic/wrap.sh b/pkgs/development/python-modules/generic/wrap.sh
index efbb1e7378763..d0c49c36c4b55 100644
--- a/pkgs/development/python-modules/generic/wrap.sh
+++ b/pkgs/development/python-modules/generic/wrap.sh
@@ -42,12 +42,12 @@ wrapPythonProgramsIn() {
                 # The magicalSedExpression will invoke a "$(basename "$f")", so
                 # if you change $f to something else, be sure to also change it
                 # in pkgs/top-level/python-packages.nix!
+                # It also uses $program_PYTHONPATH.
                 sed -i "$f" -re '@magicalSedExpression@'
                 # wrapProgram creates the executable shell script described
                 # above. The script will set PYTHONPATH and PATH variables.!
                 # (see pkgs/build-support/setup-hooks/make-wrapper.sh)
                 local -a wrap_args=("$f"
-                                 --prefix PYTHONPATH ':' "$program_PYTHONPATH"
                                  --prefix PATH ':' "$program_PATH:$dir/bin")
 
                 # Add any additional arguments provided by makeWrapperArgs
diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix
index d39c8d85cdd26..8f0b85af8c57f 100644
--- a/pkgs/top-level/python-packages.nix
+++ b/pkgs/top-level/python-packages.nix
@@ -59,13 +59,25 @@ in modules // {
           }
         '';
 
+        # This preamble does two things:
+        # * Sets argv[0] to the original application's name; otherwise it would be .foo-wrapped.
+        #   Python doesn't support `exec -a`.
+        # * Adds all required libraries to sys.path via `site.addsitedir`. It also handles *.pth files.
+        preamble = ''
+          import sys
+          import site
+          import functools
+          sys.argv[0] = '"'$(basename "$f")'"'
+          functools.reduce(lambda k, p: site.addsitedir(p, k), ['"$([ -n "$program_PYTHONPATH" ] && (echo "'$program_PYTHONPATH'" | sed "s|:|','|g") || true)"'], site._init_pathinfo())
+        '';
+
       in ''
         1 {
           /^#!/!b; :r
           /\\$/{N;br}
           /__future__|^ *(#.*)?$/{n;br}
           ${concatImapStrings mkStringSkipper quoteVariants}
-          /^ *[^# ]/i import sys; sys.argv[0] = '"'$(basename "$f")'"'
+          /^ *[^# ]/i ${replaceStrings ["\n"] [";"] preamble}
         }
       '';
     }