Just to clarify, i'm not saying that it is coupled to the test_framework, but that it is coupled to the config.
For a followup I could see something like the code below, for this PR I like that it is more or less a code move.
Rough example; not ment to be a nit:
def get_binary_paths(bin_path, exe_ext):
"""Get paths of all binaries from environment variables or their default values"""
paths = types.SimpleNamespace()
binaries = {
"bitcoin": "BITCOIN_BIN",
"bitcoind": "BITCOIND",
"bitcoin-cli": "BITCOINCLI",
"bitcoin-util": "BITCOINUTIL",
"bitcoin-tx": "BITCOINTX",
"bitcoin-chainstate": "BITCOINCHAINSTATE",
"bitcoin-wallet": "BITCOINWALLET",
}
# Set paths to bitcoin core binaries allowing overrides with environment
# variables.
for binary, env_variable_name in binaries.items():
default_filename = os.path.join(
bin_path,
binary + exe_ext,
)
setattr(paths, env_variable_name.lower(), os.getenv(env_variable_name, default=default_filename))