mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-12-21 21:23:06 +00:00
1f197e240e
Prior to this commit, pythonRelaxDeps would only support removing version constraints from "Requires-Dist" lines formatted in a particular way ("foo (>= 1.2.3)"). This way is deprecated as per PyPA Core Metadata Specs v2.1 [1]: > Tools parsing the format should accept optional parentheses around > this, but tools generating it should not use parentheses. Additionally, a "Requires-Dist" dependency specification can contain other metadata than just package name and version (extra names, environment marker). These were being silently dropped by the prior version of pythonRelaxDeps, or the version could not be relaxed. The actual grammar is defined in PEP 508 [2]. Our tool of choice here is sed extended regexps, so there's only so much we can do to be correct with this parser. The regexp implemented in this commit makes an attempt at supporting [extra] names, ; env_markers, as well as version specs without parentheses. There are still unsupported features (URL specs) as well as unhandled edge cases, but at some point trying to make the regexp better is bound to awake ZALGO [3]. [1] https://packaging.python.org/en/latest/specifications/core-metadata/#requires-dist-multiple-use [2] https://peps.python.org/pep-0508/#grammar [3] https://stackoverflow.com/a/1732454/179806
108 lines
3.1 KiB
Bash
108 lines
3.1 KiB
Bash
# shellcheck shell=bash
|
|
|
|
# Setup hook that modifies Python dependencies versions.
|
|
#
|
|
# Example usage in a derivation:
|
|
#
|
|
# { …, pythonPackages, … }:
|
|
#
|
|
# pythonPackages.buildPythonPackage {
|
|
# …
|
|
# nativeBuildInputs = [ pythonPackages.pythonRelaxDepsHook ];
|
|
#
|
|
# # This will relax the dependency restrictions
|
|
# # e.g.: abc>1,<=2 -> abc
|
|
# pythonRelaxDeps = [ "abc" ];
|
|
# # This will relax all dependencies restrictions instead
|
|
# # pythonRelaxDeps = true;
|
|
# # This will remove the dependency
|
|
# # e.g.: cde>1,<=2 -> <nothing>
|
|
# pythonRemoveDeps = [ "cde" ];
|
|
# # This will remove all dependencies from the project
|
|
# # pythonRemoveDeps = true;
|
|
# …
|
|
# }
|
|
#
|
|
# IMPLEMENTATION NOTES:
|
|
#
|
|
# The "Requires-Dist" dependency specification format is described in PEP 508.
|
|
# Examples that the regular expressions in this hook needs to support:
|
|
#
|
|
# Requires-Dist: foo
|
|
# -> foo
|
|
# Requires-Dist: foo[optional]
|
|
# -> foo[optional]
|
|
# Requires-Dist: foo[optional]~=1.2.3
|
|
# -> foo[optional]
|
|
# Requires-Dist: foo[optional, xyz] (~=1.2.3)
|
|
# -> foo[optional, xyz]
|
|
# Requires-Dist: foo[optional]~=1.2.3 ; os_name = "posix"
|
|
# -> foo[optional] ; os_name = "posix"
|
|
#
|
|
# Currently unsupported: URL specs (foo @ https://example.com/a.zip).
|
|
|
|
_pythonRelaxDeps() {
|
|
local -r metadata_file="$1"
|
|
|
|
if [[ -z "${pythonRelaxDeps:-}" ]] || [[ "$pythonRelaxDeps" == 0 ]]; then
|
|
return
|
|
elif [[ "$pythonRelaxDeps" == 1 ]]; then
|
|
sed -i "$metadata_file" -r \
|
|
-e 's/(Requires-Dist: [a-zA-Z0-9_.-]+\s*(\[[^]]+\])?)[^;]*(;.*)?/\1\3/'
|
|
else
|
|
for dep in $pythonRelaxDeps; do
|
|
sed -i "$metadata_file" -r \
|
|
-e "s/(Requires-Dist: $dep\s*(\[[^]]+\])?)[^;]*(;.*)?/\1\3/"
|
|
done
|
|
fi
|
|
}
|
|
|
|
_pythonRemoveDeps() {
|
|
local -r metadata_file="$1"
|
|
|
|
if [[ -z "${pythonRemoveDeps:-}" ]] || [[ "$pythonRemoveDeps" == 0 ]]; then
|
|
return
|
|
elif [[ "$pythonRemoveDeps" == 1 ]]; then
|
|
sed -i "$metadata_file" \
|
|
-e '/Requires-Dist:.*/d'
|
|
else
|
|
for dep in $pythonRemoveDeps; do
|
|
sed -i "$metadata_file" \
|
|
-e "/Requires-Dist: $dep/d"
|
|
done
|
|
fi
|
|
|
|
}
|
|
|
|
pythonRelaxDepsHook() {
|
|
pushd dist
|
|
|
|
# See https://peps.python.org/pep-0491/#escaping-and-unicode
|
|
local -r pkg_name="${pname//[^[:alnum:].]/_}-$version"
|
|
local -r unpack_dir="unpacked"
|
|
local -r metadata_file="$unpack_dir/$pkg_name/$pkg_name.dist-info/METADATA"
|
|
|
|
# We generally shouldn't have multiple wheel files, but let's be safer here
|
|
for wheel in "$pkg_name"*".whl"; do
|
|
@pythonInterpreter@ -m wheel unpack --dest "$unpack_dir" "$wheel"
|
|
rm -rf "$wheel"
|
|
|
|
_pythonRelaxDeps "$metadata_file"
|
|
_pythonRemoveDeps "$metadata_file"
|
|
|
|
if (( "${NIX_DEBUG:-0}" >= 1 )); then
|
|
echo "pythonRelaxDepsHook: resulting METADATA for '$wheel':"
|
|
cat "$unpack_dir/$pkg_name/$pkg_name.dist-info/METADATA"
|
|
fi
|
|
|
|
@pythonInterpreter@ -m wheel pack "$unpack_dir/$pkg_name"
|
|
done
|
|
|
|
# Remove the folder since it will otherwise be in the dist output.
|
|
rm -rf "$unpack_dir"
|
|
|
|
popd
|
|
}
|
|
|
|
postBuild+=" pythonRelaxDepsHook"
|