Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pkgs/by-name/xo/xonsh/unwrapped.nix
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ python3.pkgs.buildPythonApplication {
export HOME=$TMPDIR
'';

dontWrapPythonPrograms = true;

passthru = {
shellPath = "/bin/xonsh";
python = python3; # To the wrapper
Expand Down
2 changes: 2 additions & 0 deletions pkgs/development/interpreters/python/cpython/2.7/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,8 @@ in with passthru; stdenv.mkDerivation ({
inherit passthru;

postFixup = ''
# Include a sitecustomize.py file. Note it causes an error when it's in postInstall with 2.7.
cp ${../../sitecustomize.py} $out/${sitePackages}/sitecustomize.py
'' + lib.optionalString strip2to3 ''
rm -R $out/bin/2to3 $out/lib/python*/lib2to3
'' + lib.optionalString stripConfig ''
Expand Down
3 changes: 2 additions & 1 deletion pkgs/development/interpreters/python/cpython/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,8 @@ in with passthru; stdenv.mkDerivation (finalAttrs: {
# Strip tests
rm -R $out/lib/python*/test $out/lib/python*/**/test{,s}
'' + optionalString includeSiteCustomize ''

# Include a sitecustomize.py file
cp ${../sitecustomize.py} $out/${sitePackages}/sitecustomize.py
'' + optionalString stripBytecode ''
# Determinism: deterministic bytecode
# First we delete all old bytecode.
Expand Down
3 changes: 3 additions & 0 deletions pkgs/development/interpreters/python/pypy/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ in with passthru; stdenv.mkDerivation rec {
ln -s $out/${executable}-c/include $out/include/${libPrefix}
ln -s $out/${executable}-c/lib-python/${if isPy3k then "3" else pythonVersion} $out/lib/${libPrefix}

# Include a sitecustomize.py file
cp ${../sitecustomize.py} $out/${if isPy38OrNewer then sitePackages else "lib/${libPrefix}/${sitePackages}"}/sitecustomize.py

runHook postInstall
'';

Expand Down
3 changes: 3 additions & 0 deletions pkgs/development/interpreters/python/pypy/prebuilt.nix
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ in with passthru; stdenv.mkDerivation {
echo "Removing bytecode"
find . -name "__pycache__" -type d -depth -delete

# Include a sitecustomize.py file
cp ${../sitecustomize.py} $out/${sitePackages}/sitecustomize.py

runHook postInstall
'';

Expand Down
3 changes: 3 additions & 0 deletions pkgs/development/interpreters/python/pypy/prebuilt_2_7.nix
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ in with passthru; stdenv.mkDerivation {
echo "Removing bytecode"
find . -name "__pycache__" -type d -depth -delete

# Include a sitecustomize.py file
cp ${../sitecustomize.py} $out/${sitePackages}/sitecustomize.py

runHook postInstall
'';

Expand Down
39 changes: 39 additions & 0 deletions pkgs/development/interpreters/python/sitecustomize.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""
This is a Nix-specific module for discovering modules built with Nix.

The module recursively adds paths that are on `NIX_PYTHONPATH` to `sys.path`. In
order to process possible `.pth` files `site.addsitedir` is used.

The paths listed in `PYTHONPATH` are added to `sys.path` afterwards, but they
will be added before the entries we add here and thus take precedence.

Note the `NIX_PYTHONPATH` environment variable is unset in order to prevent leakage.

Similarly, this module listens to the environment variable `NIX_PYTHONEXECUTABLE`
and sets `sys.executable` to its value.
"""
import site
import sys
import os
import functools

paths = os.environ.pop('NIX_PYTHONPATH', None)
if paths:
functools.reduce(lambda k, p: site.addsitedir(p, k), paths.split(':'), site._init_pathinfo())

# Check whether we are in a venv or virtualenv.
# For Python 3 we check whether our `base_prefix` is different from our current `prefix`.
# For Python 2 we check whether the non-standard `real_prefix` is set.
# https://stackoverflow.com/questions/1871549/determine-if-python-is-running-inside-virtualenv
in_venv = (sys.version_info.major == 3 and sys.prefix != sys.base_prefix) or (sys.version_info.major == 2 and hasattr(sys, "real_prefix"))

if not in_venv:
executable = os.environ.pop('NIX_PYTHONEXECUTABLE', None)
prefix = os.environ.pop('NIX_PYTHONPREFIX', None)

if 'PYTHONEXECUTABLE' not in os.environ and executable is not None:
sys.executable = executable
if prefix is not None:
# Sysconfig does not like it when sys.prefix is set to None
sys.prefix = sys.exec_prefix = prefix
site.PREFIXES.insert(0, prefix)
91 changes: 18 additions & 73 deletions pkgs/development/interpreters/python/tests.nix
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,13 @@ let
is_virtualenv = "False";
};
} // lib.optionalAttrs (!python.isPyPy && !stdenv.isDarwin) {
# Use virtualenv with symlinks from a Nix env.
# Use virtualenv from a Nix env.
# Fails on darwin with
# virtualenv: error: argument dest: the destination . is not write-able at /nix/store
nixenv-virtualenv-links = rec {
env = runCommand "${python.name}-virtualenv-links" {} ''
${pythonVirtualEnv.interpreter} -m virtualenv --system-site-packages --symlinks --no-seed $out
'';
interpreter = "${env}/bin/${python.executable}";
is_venv = "False";
is_nixenv = "True";
is_virtualenv = "True";
};
} // lib.optionalAttrs (!python.isPyPy && !stdenv.isDarwin) {
# Use virtualenv with copies from a Nix env.
# Fails on darwin with
# virtualenv: error: argument dest: the destination . is not write-able at /nix/store
nixenv-virtualenv-copies = rec {
env = runCommand "${python.name}-virtualenv-copies" {} ''
${pythonVirtualEnv.interpreter} -m virtualenv --system-site-packages --copies --no-seed $out
nixenv-virtualenv = rec {
env = runCommand "${python.name}-virtualenv" {} ''
${pythonVirtualEnv.interpreter} -m virtualenv venv
mv venv $out
'';
interpreter = "${env}/bin/${python.executable}";
is_venv = "False";
Expand All @@ -73,48 +61,27 @@ let
is_nixenv = "True";
is_virtualenv = "False";
};
} // lib.optionalAttrs (python.pythonAtLeast "3.8" && (!python.isPyPy)) {
# Venv built using links to plain Python
# Python 2 does not support venv
# TODO: PyPy executable name is incorrect, it should be pypy-c or pypy-3c instead of pypy and pypy3.
plain-venv-links = rec {
env = runCommand "${python.name}-venv-links" {} ''
${python.interpreter} -m venv --system-site-packages --symlinks --without-pip $out
'';
interpreter = "${env}/bin/${python.executable}";
is_venv = "True";
is_nixenv = "False";
is_virtualenv = "False";
};
} // lib.optionalAttrs (python.pythonAtLeast "3.8" && (!python.isPyPy)) {
# Venv built using copies from plain Python
} // lib.optionalAttrs (python.isPy3k && (!python.isPyPy)) {
# Venv built using plain Python
# Python 2 does not support venv
# TODO: PyPy executable name is incorrect, it should be pypy-c or pypy-3c instead of pypy and pypy3.
plain-venv-copies = rec {
env = runCommand "${python.name}-venv-copies" {} ''
${python.interpreter} -m venv --system-site-packages --copies --without-pip $out
plain-venv = rec {
env = runCommand "${python.name}-venv" {} ''
${python.interpreter} -m venv $out
'';
interpreter = "${env}/bin/${python.executable}";
is_venv = "True";
is_nixenv = "False";
is_virtualenv = "False";
};

} // lib.optionalAttrs (python.pythonAtLeast "3.8") {
# Venv built using Python Nix environment (python.buildEnv)
nixenv-venv-links = rec {
env = runCommand "${python.name}-venv-links" {} ''
${pythonEnv.interpreter} -m venv --system-site-packages --symlinks --without-pip $out
'';
interpreter = "${env}/bin/${pythonEnv.executable}";
is_venv = "True";
is_nixenv = "True";
is_virtualenv = "False";
};
} // lib.optionalAttrs (python.pythonAtLeast "3.8") {
# Venv built using Python Nix environment (python.buildEnv)
nixenv-venv-copies = rec {
env = runCommand "${python.name}-venv-copies" {} ''
${pythonEnv.interpreter} -m venv --system-site-packages --copies --without-pip $out
# TODO: Cannot create venv from a nix env
# Error: Command '['/nix/store/ddc8nqx73pda86ibvhzdmvdsqmwnbjf7-python3-3.7.6-venv/bin/python3.7', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1.
nixenv-venv = rec {
env = runCommand "${python.name}-venv" {} ''
${pythonEnv.interpreter} -m venv $out
'';
interpreter = "${env}/bin/${pythonEnv.executable}";
is_venv = "True";
Expand All @@ -126,33 +93,11 @@ let
testfun = name: attrs: runCommand "${python.name}-tests-${name}" ({
inherit (python) pythonVersion;
} // attrs) ''
mkdir $out

# set up the test files
cp -r ${./tests/test_environments} tests
chmod -R +w tests
substituteAllInPlace tests/test_python.py

# run the tests by invoking the interpreter via full path
echo "absolute path: ${attrs.interpreter}"
${attrs.interpreter} -m unittest discover --verbose tests 2>&1 | tee "$out/full.txt"

# run the tests by invoking the interpreter via $PATH
export PATH="$(dirname ${attrs.interpreter}):$PATH"
echo "PATH: $(basename ${attrs.interpreter})"
"$(basename ${attrs.interpreter})" -m unittest discover --verbose tests 2>&1 | tee "$out/path.txt"

# make sure we get the right path when invoking through a result link
ln -s "${attrs.env}" result
relative="result/bin/$(basename ${attrs.interpreter})"
expected="$PWD/$relative"
actual="$(./$relative -c "import sys; print(sys.executable)" | tee "$out/result.txt")"
if [ "$actual" != "$expected" ]; then
echo "expected $expected, got $actual"
exit 1
fi

# if we got this far, the tests passed
${attrs.interpreter} -m unittest discover --verbose tests #/test_python.py
mkdir $out
touch $out/success
'';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def test_site_prefix(self):

@unittest.skipIf(IS_PYPY or sys.version_info.major==2, "Python 2 does not have base_prefix")
def test_base_prefix(self):
if IS_VENV or IS_VIRTUALENV:
if IS_VENV or IS_NIXENV or IS_VIRTUALENV:
self.assertNotEqual(sys.prefix, sys.base_prefix)
else:
self.assertEqual(sys.prefix, sys.base_prefix)
Expand Down
10 changes: 1 addition & 9 deletions pkgs/development/interpreters/python/wrapper.nix
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,14 @@ let
fi
mkdir -p "$out/bin"

rm -f $out/bin/.*-wrapped

for path in ${lib.concatStringsSep " " paths}; do
if [ -d "$path/bin" ]; then
cd "$path/bin"
for prg in *; do
if [ -f "$prg" ]; then
rm -f "$out/bin/$prg"
if [ -x "$prg" ]; then
if [ -f ".$prg-wrapped" ]; then
echo "#!${pythonExecutable}" > "$out/bin/$prg"
sed -e '1d' -e '3d' ".$prg-wrapped" >> "$out/bin/$prg"
chmod +x "$out/bin/$prg"
else
makeWrapper "$path/bin/$prg" "$out/bin/$prg" --inherit-argv0 --resolve-argv0 ${lib.optionalString (!permitUserSite) ''--set PYTHONNOUSERSITE "true"''} ${lib.concatStringsSep " " makeWrapperArgs}
fi
makeWrapper "$path/bin/$prg" "$out/bin/$prg" --set NIX_PYTHONPREFIX "$out" --set NIX_PYTHONEXECUTABLE ${pythonExecutable} --set NIX_PYTHONPATH ${pythonPath} ${lib.optionalString (!permitUserSite) ''--set PYTHONNOUSERSITE "true"''} ${lib.concatStringsSep " " makeWrapperArgs}
fi
fi
done
Expand Down