From 006c7936a2e92017d4d7812baeeb9f0dea1fc8f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=BCtz?= Date: Wed, 17 Jun 2026 12:18:27 -0700 Subject: [PATCH] python3Packages.pythonMetadataCheckHook: init --- .../interpreters/python/hooks/default.nix | 14 +++++++ .../hooks/python-metadata-check-hook.sh | 37 +++++++++++++++++++ .../python/mk-python-derivation.nix | 16 ++++++++ 3 files changed, 67 insertions(+) create mode 100644 pkgs/development/interpreters/python/hooks/python-metadata-check-hook.sh diff --git a/pkgs/development/interpreters/python/hooks/default.nix b/pkgs/development/interpreters/python/hooks/default.nix index f5f8dc59c072..4982332e88d1 100644 --- a/pkgs/development/interpreters/python/hooks/default.nix +++ b/pkgs/development/interpreters/python/hooks/default.nix @@ -361,6 +361,20 @@ in } ./python-imports-check-hook.sh ) { }; + pythonMetadataCheckHook = callPackage ( + { makePythonHook }: + makePythonHook { + name = "python-metadata-check-hook.sh"; + substitutions = { + inherit pythonInterpreter pythonSitePackages; + pythonWithPackaging = lib.getExe (pythonOnBuildForHost.withPackages (ps: [ ps.packaging ])); + }; + meta = { + maintainers = [ lib.maintainers.dotlambda ]; + }; + } ./python-metadata-check-hook.sh + ) { }; + pythonNamespacesHook = callPackage ( { makePythonHook, buildPackages }: makePythonHook { diff --git a/pkgs/development/interpreters/python/hooks/python-metadata-check-hook.sh b/pkgs/development/interpreters/python/hooks/python-metadata-check-hook.sh new file mode 100644 index 000000000000..f942e5bee76a --- /dev/null +++ b/pkgs/development/interpreters/python/hooks/python-metadata-check-hook.sh @@ -0,0 +1,37 @@ +# shellcheck shell=bash + +# Setup hook for checking whether metadata in .dist-info matches the derivation +echo "Sourcing python-metadata-check-hook.sh" + +pythonMetadataCheckPhase() { + echo "Executing pythonMetadataCheckPhase" + + # shellcheck disable=SC2154 + pythonMetadataCheckOutput="$out" + if [[ -n "${python-}" ]]; then + echo "Using python specific output \$python for metadata check" + pythonMetadataCheckOutput=$python + fi + # shellcheck disable=SC2154 + derivationPname="$pname" + # shellcheck disable=SC2154 + derivationVersion="$version" + # `python -P` avoids picking up egg-info dirs in $PWD + metadataVersion="$(PYTHONPATH="$pythonMetadataCheckOutput/@pythonSitePackages@:$PYTHONPATH" \ + @pythonInterpreter@ -P -c 'from importlib.metadata import version; import sys; print(version(sys.argv[1]))' "$derivationPname")" + + # chethat both versions can be parsed + @pythonWithPackaging@ -c "from packaging.version import Version; from sys import argv; Version(argv[1]); Version(argv[2])" "$derivationVersion" "$metadataVersion" + + if @pythonWithPackaging@ -c "from packaging.version import Version; from sys import argv, exit; exit(Version(argv[1]) == Version(argv[2]))" "$derivationVersion" "$metadataVersion"; then + echo "The '$derivationPname' derivation has version '$derivationVersion' but .dist-info/METADATA specifies version '$metadataVersion'." + echo "This usually means that the wrong version is hardcoded in pyproject.toml or setup.{py,cfg}." + echo "Use the pyprojectVersionPatchHook or patch the version manually so that the project metadata matches the derivation's version." + exit 1 + fi +} + +if [ -z "${dontCheckPythonMetadata-}" ]; then + echo "Using pythonMetadataCheckPhase" + appendToVar preDistPhases pythonMetadataCheckPhase +fi diff --git a/pkgs/development/interpreters/python/mk-python-derivation.nix b/pkgs/development/interpreters/python/mk-python-derivation.nix index bc44a7de7178..48748b5eec77 100644 --- a/pkgs/development/interpreters/python/mk-python-derivation.nix +++ b/pkgs/development/interpreters/python/mk-python-derivation.nix @@ -18,6 +18,7 @@ pypaInstallHook, pythonCatchConflictsHook, pythonImportsCheckHook, + pythonMetadataCheckHook, pythonNamespacesHook, pythonOutputDistHook, pythonRelaxDepsHook, @@ -358,6 +359,21 @@ lib.extendMkDerivation { # This is a test, however, it should be ran independent of the checkPhase and checkInputs pythonImportsCheckHook ] + ++ + optionals + ( + finalAttrs ? "pname" + && finalAttrs ? "version" + # We don't care about the METADATA of Python applications. + && isPythonModule finalAttrs.passthru + # METADATA is unlikely to be correct if pyproject is false or null. + && pyproject == true + && !lib.hasInfix "unstable-" finalAttrs.version + && !isBootstrapPackage + ) + [ + pythonMetadataCheckHook + ] ++ optionals (python.pythonAtLeast "3.3") [ # Optionally enforce PEP420 for python3 pythonNamespacesHook