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