From 8e4e3c90602e96479214d29bac1ce122e6999679 Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Wed, 9 Oct 2024 09:08:27 +0200 Subject: [PATCH] python: rework how we compute the "command" property (#46850) Some Windows Python installations may store the Python exe in Scripts/ rather than the base directory. Update `.command` to search in both locations on Windows. On all systems, the search is now done recursively from the search root: on Windows, that is the base install directory, and on other systems it is bin/. --- lib/spack/llnl/util/filesystem.py | 1 + .../repos/builtin/packages/python/package.py | 21 ++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/spack/llnl/util/filesystem.py b/lib/spack/llnl/util/filesystem.py index 54ace7d42fa4cf..00bb270151908c 100644 --- a/lib/spack/llnl/util/filesystem.py +++ b/lib/spack/llnl/util/filesystem.py @@ -47,6 +47,7 @@ "copy_mode", "filter_file", "find", + "find_first", "find_headers", "find_all_headers", "find_libraries", diff --git a/var/spack/repos/builtin/packages/python/package.py b/var/spack/repos/builtin/packages/python/package.py index cba63ece181b4c..5db16ec17504f8 100644 --- a/var/spack/repos/builtin/packages/python/package.py +++ b/var/spack/repos/builtin/packages/python/package.py @@ -858,14 +858,14 @@ def command(self): # * python # # in that order if using python@3.11.0, for example. - version = self.spec.version - for ver in [version.up_to(2), version.up_to(1), ""]: - if sys.platform != "win32": - path = os.path.join(self.prefix.bin, "python{0}".format(ver)) - else: - path = os.path.join(self.prefix, "python{0}.exe".format(ver)) - if os.path.exists(path): - return Executable(path) + suffixes = [self.spec.version.up_to(2), self.spec.version.up_to(1), ""] + file_extension = "" if sys.platform != "win32" else ".exe" + patterns = [f"python{ver}{file_extension}" for ver in suffixes] + root = self.prefix.bin if sys.platform != "win32" else self.prefix + path = find_first(root, files=patterns) + + if path is not None: + return Executable(path) else: # Give a last try at rhel8 platform python @@ -874,8 +874,9 @@ def command(self): if os.path.exists(path): return Executable(path) - msg = "Unable to locate {0} command in {1}" - raise RuntimeError(msg.format(self.name, self.prefix.bin)) + raise RuntimeError( + f"cannot to locate the '{self.name}' command in {root} or its subdirectories" + ) @property def config_vars(self):