Replace exe_exists function with shutil.which()

The documentation for subprocess.run at https://docs.python.org/3/library/subprocess.html#popen-constructor has a warning,
pointing to using shutil.which() instead of subprocess.run for detecting if exe files exists on the path.

shutil.which() is used in many places already.
pull/13086/merge
Mads Andreasen 8 months ago committed by Jussi Pakkanen
parent f01ae52bc2
commit 50704bced3
  1. 6
      mesonbuild/environment.py
  2. 4
      mesonbuild/scripts/coverage.py
  3. 11
      mesonbuild/utils/universal.py
  4. 5
      unittests/internaltests.py

@ -109,13 +109,13 @@ def detect_llvm_cov(suffix: T.Optional[str] = None):
tool = 'llvm-cov'
else:
tool = f'llvm-cov-{suffix}'
if mesonlib.exe_exists([tool, '--version']):
if shutil.which(tool) is not None:
return tool
else:
# Otherwise guess in the dark
tools = get_llvm_tool_names('llvm-cov')
for tool in tools:
if mesonlib.exe_exists([tool, '--version']):
if shutil.which(tool):
return tool
return None
@ -139,7 +139,7 @@ def compute_llvm_suffix(coredata: coredata.CoreData):
def detect_lcov_genhtml(lcov_exe: str = 'lcov', genhtml_exe: str = 'genhtml'):
lcov_exe, lcov_version = detect_lcov(lcov_exe)
if not mesonlib.exe_exists([genhtml_exe, '--version']):
if shutil.which(genhtml_exe) is None:
genhtml_exe = None
return lcov_exe, lcov_version, genhtml_exe

@ -5,7 +5,7 @@ from __future__ import annotations
from mesonbuild import environment, mesonlib
import argparse, re, sys, os, subprocess, pathlib, stat
import argparse, re, sys, os, subprocess, pathlib, stat, shutil
import typing as T
def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build_root: str, log_dir: str, use_llvm_cov: bool,
@ -17,7 +17,7 @@ def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build
gcovr_exe = None
else:
gcovr_exe, gcovr_version = environment.detect_gcovr(gcovr_exe)
if llvm_cov_exe == '' or not mesonlib.exe_exists([llvm_cov_exe, '--version']):
if llvm_cov_exe == '' or shutil.which(llvm_cov_exe) is None:
llvm_cov_exe = None
lcov_exe, lcov_version, genhtml_exe = environment.detect_lcov_genhtml()

@ -98,7 +98,6 @@ __all__ = [
'do_conf_file',
'do_conf_str',
'do_replacement',
'exe_exists',
'expand_arguments',
'extract_as_list',
'first',
@ -683,14 +682,8 @@ def is_qnx() -> bool:
def is_aix() -> bool:
return platform.system().lower() == 'aix'
def exe_exists(arglist: T.List[str]) -> bool:
try:
if subprocess.run(arglist, timeout=10).returncode == 0:
return True
except (FileNotFoundError, subprocess.TimeoutExpired):
pass
return False
def exe_exists(exe: str) -> bool:
return shutil.which(exe) is not None
@lru_cache(maxsize=None)
def darwin_get_object_archs(objpath: str) -> 'ImmutableListProtocol[str]':

@ -39,6 +39,7 @@ from mesonbuild.interpreter.type_checking import in_set_validator, NoneType
from mesonbuild.dependencies.pkgconfig import PkgConfigDependency, PkgConfigInterface, PkgConfigCLI
from mesonbuild.programs import ExternalProgram
import mesonbuild.modules.pkgconfig
from mesonbuild import utils
from run_tests import (
@ -813,6 +814,10 @@ class InternalTests(unittest.TestCase):
self.assertTrue(vctools_ver.startswith(toolset_ver),
msg=f'{vctools_ver!r} does not start with {toolset_ver!r}')
def test_exe_exists(self):
self.assertTrue(utils.universal.exe_exists('python3'))
self.assertFalse(utils.universal.exe_exists('command_that_does_not_exist'))
def test_split_args(self):
split_args = mesonbuild.mesonlib.split_args
join_args = mesonbuild.mesonlib.join_args

Loading…
Cancel
Save