at master 3.4 kB view raw
1# shellcheck shell=bash 2 3# Setup hook that modifies Python dependencies versions. 4# 5# Example usage in a derivation: 6# 7# { …, python3Packages, … }: 8# 9# python3Packages.buildPythonPackage { 10# … 11# # This will relax the dependency restrictions 12# # e.g.: abc>1,<=2 -> abc 13# pythonRelaxDeps = [ "abc" ]; 14# # This will relax all dependencies restrictions instead 15# # pythonRelaxDeps = true; 16# # This will remove the dependency 17# # e.g.: cde>1,<=2 -> <nothing> 18# pythonRemoveDeps = [ "cde" ]; 19# # This will remove all dependencies from the project 20# # pythonRemoveDeps = true; 21# … 22# } 23# 24# IMPLEMENTATION NOTES: 25# 26# The "Requires-Dist" dependency specification format is described in PEP 508. 27# Examples that the regular expressions in this hook needs to support: 28# 29# Requires-Dist: foo 30# -> foo 31# Requires-Dist: foo[optional] 32# -> foo[optional] 33# Requires-Dist: foo[optional]~=1.2.3 34# -> foo[optional] 35# Requires-Dist: foo[optional, xyz] (~=1.2.3) 36# -> foo[optional, xyz] 37# Requires-Dist: foo[optional]~=1.2.3 ; os_name = "posix" 38# -> foo[optional] ; os_name = "posix" 39# 40# Currently unsupported: URL specs (foo @ https://example.com/a.zip). 41 42_pythonRelaxDeps() { 43 local -r metadata_file="$1" 44 45 if [[ -z "${pythonRelaxDeps[*]-}" ]] || [[ "$pythonRelaxDeps" == 0 ]]; then 46 return 47 elif [[ "$pythonRelaxDeps" == 1 ]]; then 48 sed -i "$metadata_file" -r \ 49 -e 's/(Requires-Dist: [a-zA-Z0-9_.-]+\s*(\[[^]]+\])?)[^;]*(;.*)?/\1\3/' 50 else 51 # shellcheck disable=SC2048 52 for dep in ${pythonRelaxDeps[*]}; do 53 sed -i "$metadata_file" -r \ 54 -e "s/(Requires-Dist: $dep\s*(\[[^]]+\])?)[^;]*(;.*)?/\1\3/i" 55 done 56 fi 57} 58 59_pythonRemoveDeps() { 60 local -r metadata_file="$1" 61 62 if [[ -z "${pythonRemoveDeps[*]-}" ]] || [[ "$pythonRemoveDeps" == 0 ]]; then 63 return 64 elif [[ "$pythonRemoveDeps" == 1 ]]; then 65 sed -i "$metadata_file" \ 66 -e '/Requires-Dist:.*/d' 67 else 68 # shellcheck disable=SC2048 69 for dep in ${pythonRemoveDeps[*]-}; do 70 sed -i "$metadata_file" \ 71 -e "/Requires-Dist: $dep/d" 72 done 73 fi 74 75} 76 77pythonRelaxDepsHook() { 78 pushd dist 79 80 local -r unpack_dir="unpacked" 81 local -r metadata_file="$unpack_dir/*/*.dist-info/METADATA" 82 83 # We generally shouldn't have multiple wheel files, but let's be safer here 84 for wheel in *".whl"; do 85 86 PYTHONPATH="@wheel@/@pythonSitePackages@:$PYTHONPATH" \ 87 @pythonInterpreter@ -m wheel unpack --dest "$unpack_dir" "$wheel" 88 rm -rf "$wheel" 89 90 # Using no quotes on purpose since we need to expand the glob from `$metadata_file` 91 # shellcheck disable=SC2086 92 _pythonRelaxDeps $metadata_file 93 # shellcheck disable=SC2086 94 _pythonRemoveDeps $metadata_file 95 96 if (("${NIX_DEBUG:-0}" >= 1)); then 97 echo "pythonRelaxDepsHook: resulting METADATA for '$wheel':" 98 # shellcheck disable=SC2086 99 cat $metadata_file 100 fi 101 102 PYTHONPATH="@wheel@/@pythonSitePackages@:$PYTHONPATH" \ 103 @pythonInterpreter@ -m wheel pack "$unpack_dir/"* 104 done 105 106 # Remove the folder since it will otherwise be in the dist output. 107 rm -rf "$unpack_dir" 108 109 popd 110} 111 112postBuild+=" pythonRelaxDepsHook"