From 2651ddc7b0788932df9da7416ccd1618d76c11fe Mon Sep 17 00:00:00 2001 From: phaer Date: Fri, 26 Jan 2024 18:24:26 +0100 Subject: [PATCH] python/catch_conflicts: scan $out, not sys.path This changes the non-legacy version of pythonCatchConflictsHook to recursively scan the output of the target derivation as well as its propagatedBuildInputs for duplicate dependencies. Previously, we did scan sys.path but did prove problematic as it produced false positives i.e. when build-time dependencies of hooks - such as setuptools in pythonCatchConflictsHook itself - where mistakenly flagged as duplicates; even though the are not included in the outputs of the target dervation. As all python runtime-dependencies are currently passed via propagatedBuildInputs in nixpkgs, scanning that plus site-packages seems sufficient to catch all conflicts that matter at runtime and less likely to produce false positives. The legacyHook in catch_conflicts_py2.py needs to be migrated as well, if it's still needed. --- .../python/catch_conflicts/catch_conflicts.py | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/pkgs/development/interpreters/python/catch_conflicts/catch_conflicts.py b/pkgs/development/interpreters/python/catch_conflicts/catch_conflicts.py index d5c99e64751c..9339c62a6399 100644 --- a/pkgs/development/interpreters/python/catch_conflicts/catch_conflicts.py +++ b/pkgs/development/interpreters/python/catch_conflicts/catch_conflicts.py @@ -2,21 +2,35 @@ from importlib.metadata import PathDistribution from pathlib import Path import collections import sys +import os do_abort = False packages = collections.defaultdict(list) +out_path = Path(os.getenv("out")) +version = sys.version_info +site_packages_path = f'lib/python{version[0]}.{version[1]}/site-packages' -for path in sys.path: - for dist_info in Path(path).glob("*.dist-info"): - dist = PathDistribution(dist_info) +def find_packages(store_path, site_packages_path): + site_packages = (store_path / site_packages_path) + propagated_build_inputs = (store_path / "nix-support/propagated-build-inputs") + if site_packages.exists(): + for dist_info in site_packages.glob("*.dist-info"): + dist = PathDistribution(dist_info) + packages[dist._normalized_name].append( + f"{dist._normalized_name} {dist.version} ({dist._path})" + ) - packages[dist._normalized_name].append( - f"{dist._normalized_name} {dist.version} ({dist._path})" - ) + if propagated_build_inputs.exists(): + with open(propagated_build_inputs, "r") as f: + build_inputs = f.read().strip().split(" ") + for build_input in build_inputs: + find_packages(Path(build_input), site_packages_path) +find_packages(out_path, site_packages_path) + for name, duplicates in packages.items(): if len(duplicates) > 1: do_abort = True