Skip to content

Commit d98d88c

Browse files
committed
Merge bitcoin#28392: test: Use pathlib over os path
bfa0bd6 test: Use pathlib over os.path bitcoin#28362 (ns-xvrn) Pull request description: In reference to issue bitcoin#28362 refactoring of functional tests to use pathlib over os.path to reduce verbosity and increase the intuitiveness of managing file access. ACKs for top commit: maflcko: re-ACK bfa0bd6 🐨 willcl-ark: ACK bfa0bd6 Tree-SHA512: fb0833c4039d09758796514e47567a93ac831cb0776ff1a7ed8299792ad132e83282ef80bea098a88ae1551d906f2a56093d3e8de240412f9080735d00d496d9
2 parents 744157e + bfa0bd6 commit d98d88c

22 files changed

+138
-168
lines changed

test/functional/feature_blocksdir.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
"""Test the blocksdir option.
66
"""
77

8-
import os
98
import shutil
9+
from pathlib import Path
1010

1111
from test_framework.test_framework import BitcoinTestFramework, initialize_datadir
1212

@@ -18,20 +18,20 @@ def set_test_params(self):
1818

1919
def run_test(self):
2020
self.stop_node(0)
21-
assert os.path.isdir(os.path.join(self.nodes[0].blocks_path))
22-
assert not os.path.isdir(os.path.join(self.nodes[0].datadir, "blocks"))
23-
shutil.rmtree(self.nodes[0].datadir)
21+
assert self.nodes[0].blocks_path.is_dir()
22+
assert not (self.nodes[0].datadir_path / "blocks").is_dir()
23+
shutil.rmtree(self.nodes[0].datadir_path)
2424
initialize_datadir(self.options.tmpdir, 0, self.chain)
2525
self.log.info("Starting with nonexistent blocksdir ...")
26-
blocksdir_path = os.path.join(self.options.tmpdir, 'blocksdir')
26+
blocksdir_path = Path(self.options.tmpdir) / 'blocksdir'
2727
self.nodes[0].assert_start_raises_init_error([f"-blocksdir={blocksdir_path}"], f'Error: Specified blocks directory "{blocksdir_path}" does not exist.')
28-
os.mkdir(blocksdir_path)
28+
blocksdir_path.mkdir()
2929
self.log.info("Starting with existing blocksdir ...")
3030
self.start_node(0, [f"-blocksdir={blocksdir_path}"])
3131
self.log.info("mining blocks..")
3232
self.generatetoaddress(self.nodes[0], 10, self.nodes[0].get_deterministic_priv_key().address)
33-
assert os.path.isfile(os.path.join(blocksdir_path, self.chain, "blocks", "blk00000.dat"))
34-
assert os.path.isdir(os.path.join(self.nodes[0].blocks_path, "index"))
33+
assert (blocksdir_path / self.chain / "blocks" / "blk00000.dat").is_file()
34+
assert (self.nodes[0].blocks_path / "index").is_dir()
3535

3636

3737
if __name__ == '__main__':

test/functional/feature_config_args.py

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"""Test various command line arguments and configuration file parameters."""
66

77
import os
8-
import pathlib
8+
from pathlib import Path
99
import re
1010
import sys
1111
import tempfile
@@ -39,8 +39,8 @@ def test_config_file_parser(self):
3939
extra_args=[f'-conf={bad_conf_file_path}'],
4040
expected_msg=conf_in_config_file_err,
4141
)
42-
inc_conf_file_path = os.path.join(self.nodes[0].datadir, 'include.conf')
43-
with open(os.path.join(self.nodes[0].datadir, 'bitcoin.conf'), 'a', encoding='utf-8') as conf:
42+
inc_conf_file_path = self.nodes[0].datadir_path / 'include.conf'
43+
with open(self.nodes[0].datadir_path / 'bitcoin.conf', 'a', encoding='utf-8') as conf:
4444
conf.write(f'includeconf={inc_conf_file_path}\n')
4545
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
4646
conf.write('conf=some.conf\n')
@@ -97,8 +97,8 @@ def test_config_file_parser(self):
9797
conf.write('server=1\nrpcuser=someuser\n[main]\nrpcpassword=some#pass')
9898
self.nodes[0].assert_start_raises_init_error(expected_msg='Error: Error reading configuration file: parse error on line 4, using # in rpcpassword can be ambiguous and should be avoided')
9999

100-
inc_conf_file2_path = os.path.join(self.nodes[0].datadir, 'include2.conf')
101-
with open(os.path.join(self.nodes[0].datadir, 'bitcoin.conf'), 'a', encoding='utf-8') as conf:
100+
inc_conf_file2_path = self.nodes[0].datadir_path / 'include2.conf'
101+
with open(self.nodes[0].datadir_path / 'bitcoin.conf', 'a', encoding='utf-8') as conf:
102102
conf.write(f'includeconf={inc_conf_file2_path}\n')
103103

104104
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
@@ -123,15 +123,15 @@ def test_config_file_log(self):
123123

124124
# Create a temporary directory that will be treated as the default data
125125
# directory by bitcoind.
126-
env, default_datadir = util.get_temp_default_datadir(pathlib.Path(self.options.tmpdir, "test_config_file_log"))
126+
env, default_datadir = util.get_temp_default_datadir(Path(self.options.tmpdir, "test_config_file_log"))
127127
default_datadir.mkdir(parents=True)
128128

129129
# Write a bitcoin.conf file in the default data directory containing a
130130
# datadir= line pointing at the node datadir.
131131
node = self.nodes[0]
132-
conf_text = pathlib.Path(node.bitcoinconf).read_text()
132+
conf_text = node.bitcoinconf.read_text()
133133
conf_path = default_datadir / "bitcoin.conf"
134-
conf_path.write_text(f"datadir={node.datadir}\n{conf_text}")
134+
conf_path.write_text(f"datadir={node.datadir_path}\n{conf_text}")
135135

136136
# Drop the node -datadir= argument during this test, because if it is
137137
# specified it would take precedence over the datadir setting in the
@@ -218,7 +218,8 @@ def test_networkactive(self):
218218

219219
def test_seed_peers(self):
220220
self.log.info('Test seed peers')
221-
default_data_dir = self.nodes[0].datadir
221+
default_data_dir = self.nodes[0].datadir_path
222+
peer_dat = default_data_dir / 'peers.dat'
222223
# Only regtest has no fixed seeds. To avoid connections to random
223224
# nodes, regtest is the only network where it is safe to enable
224225
# -fixedseeds in tests
@@ -229,7 +230,7 @@ def test_seed_peers(self):
229230
# We expect the node will use DNS Seeds, but Regtest mode does not have
230231
# any valid DNS seeds. So after 60 seconds, the node should fallback to
231232
# fixed seeds
232-
assert not os.path.exists(os.path.join(default_data_dir, "peers.dat"))
233+
assert not peer_dat.exists()
233234
start = int(time.time())
234235
with self.nodes[0].assert_debug_log(
235236
expected_msgs=[
@@ -248,7 +249,7 @@ def test_seed_peers(self):
248249

249250
# No peers.dat exists and -dnsseed=0
250251
# We expect the node will fallback immediately to fixed seeds
251-
assert not os.path.exists(os.path.join(default_data_dir, "peers.dat"))
252+
assert not peer_dat.exists()
252253
with self.nodes[0].assert_debug_log(expected_msgs=[
253254
"Loaded 0 addresses from peers.dat",
254255
"DNS seeding disabled",
@@ -260,7 +261,7 @@ def test_seed_peers(self):
260261

261262
# No peers.dat exists and dns seeds are disabled.
262263
# We expect the node will not add fixed seeds when explicitly disabled.
263-
assert not os.path.exists(os.path.join(default_data_dir, "peers.dat"))
264+
assert not peer_dat.exists()
264265
with self.nodes[0].assert_debug_log(expected_msgs=[
265266
"Loaded 0 addresses from peers.dat",
266267
"DNS seeding disabled",
@@ -271,7 +272,7 @@ def test_seed_peers(self):
271272

272273
# No peers.dat exists and -dnsseed=0, but a -addnode is provided
273274
# We expect the node will allow 60 seconds prior to using fixed seeds
274-
assert not os.path.exists(os.path.join(default_data_dir, "peers.dat"))
275+
assert not peer_dat.exists()
275276
start = int(time.time())
276277
with self.nodes[0].assert_debug_log(
277278
expected_msgs=[
@@ -323,16 +324,16 @@ def test_ignored_conf(self):
323324
'because a conflicting -conf file argument is passed.')
324325
node = self.nodes[0]
325326
with tempfile.NamedTemporaryFile(dir=self.options.tmpdir, mode="wt", delete=False) as temp_conf:
326-
temp_conf.write(f"datadir={node.datadir}\n")
327+
temp_conf.write(f"datadir={node.datadir_path}\n")
327328
node.assert_start_raises_init_error([f"-conf={temp_conf.name}"], re.escape(
328-
f'Error: Data directory "{node.datadir}" contains a "bitcoin.conf" file which is ignored, because a '
329+
f'Error: Data directory "{node.datadir_path}" contains a "bitcoin.conf" file which is ignored, because a '
329330
f'different configuration file "{temp_conf.name}" from command line argument "-conf={temp_conf.name}" '
330331
f'is being used instead.') + r"[\s\S]*", match=ErrorMatch.FULL_REGEX)
331332

332333
# Test that passing a redundant -conf command line argument pointing to
333334
# the same bitcoin.conf that would be loaded anyway does not trigger an
334335
# error.
335-
self.start_node(0, [f'-conf={node.datadir}/bitcoin.conf'])
336+
self.start_node(0, [f'-conf={node.datadir_path}/bitcoin.conf'])
336337
self.stop_node(0)
337338

338339
def test_ignored_default_conf(self):
@@ -346,23 +347,23 @@ def test_ignored_default_conf(self):
346347

347348
# Create a temporary directory that will be treated as the default data
348349
# directory by bitcoind.
349-
env, default_datadir = util.get_temp_default_datadir(pathlib.Path(self.options.tmpdir, "home"))
350+
env, default_datadir = util.get_temp_default_datadir(Path(self.options.tmpdir, "home"))
350351
default_datadir.mkdir(parents=True)
351352

352353
# Write a bitcoin.conf file in the default data directory containing a
353354
# datadir= line pointing at the node datadir. This will trigger a
354355
# startup error because the node datadir contains a different
355356
# bitcoin.conf that would be ignored.
356357
node = self.nodes[0]
357-
(default_datadir / "bitcoin.conf").write_text(f"datadir={node.datadir}\n")
358+
(default_datadir / "bitcoin.conf").write_text(f"datadir={node.datadir_path}\n")
358359

359360
# Drop the node -datadir= argument during this test, because if it is
360361
# specified it would take precedence over the datadir setting in the
361362
# config file.
362363
node_args = node.args
363364
node.args = [arg for arg in node.args if not arg.startswith("-datadir=")]
364365
node.assert_start_raises_init_error([], re.escape(
365-
f'Error: Data directory "{node.datadir}" contains a "bitcoin.conf" file which is ignored, because a '
366+
f'Error: Data directory "{node.datadir_path}" contains a "bitcoin.conf" file which is ignored, because a '
366367
f'different configuration file "{default_datadir}/bitcoin.conf" from data directory "{default_datadir}" '
367368
f'is being used instead.') + r"[\s\S]*", env=env, match=ErrorMatch.FULL_REGEX)
368369
node.args = node_args
@@ -392,16 +393,16 @@ def run_test(self):
392393
# Remove the -datadir argument so it doesn't override the config file
393394
self.nodes[0].args = [arg for arg in self.nodes[0].args if not arg.startswith("-datadir")]
394395

395-
default_data_dir = self.nodes[0].datadir
396-
new_data_dir = os.path.join(default_data_dir, 'newdatadir')
397-
new_data_dir_2 = os.path.join(default_data_dir, 'newdatadir2')
396+
default_data_dir = self.nodes[0].datadir_path
397+
new_data_dir = default_data_dir / 'newdatadir'
398+
new_data_dir_2 = default_data_dir / 'newdatadir2'
398399

399400
# Check that using -datadir argument on non-existent directory fails
400-
self.nodes[0].datadir = new_data_dir
401+
self.nodes[0].datadir_path = new_data_dir
401402
self.nodes[0].assert_start_raises_init_error([f'-datadir={new_data_dir}'], f'Error: Specified data directory "{new_data_dir}" does not exist.')
402403

403404
# Check that using non-existent datadir in conf file fails
404-
conf_file = os.path.join(default_data_dir, "bitcoin.conf")
405+
conf_file = default_data_dir / "bitcoin.conf"
405406

406407
# datadir needs to be set before [chain] section
407408
with open(conf_file, encoding='utf8') as f:
@@ -413,20 +414,20 @@ def run_test(self):
413414
self.nodes[0].assert_start_raises_init_error([f'-conf={conf_file}'], f'Error: Error reading configuration file: specified data directory "{new_data_dir}" does not exist.')
414415

415416
# Check that an explicitly specified config file that cannot be opened fails
416-
none_existent_conf_file = os.path.join(default_data_dir, "none_existent_bitcoin.conf")
417-
self.nodes[0].assert_start_raises_init_error(['-conf=' + none_existent_conf_file], 'Error: Error reading configuration file: specified config file "' + none_existent_conf_file + '" could not be opened.')
417+
none_existent_conf_file = default_data_dir / "none_existent_bitcoin.conf"
418+
self.nodes[0].assert_start_raises_init_error(['-conf=' + f'{none_existent_conf_file}'], 'Error: Error reading configuration file: specified config file "' + f'{none_existent_conf_file}' + '" could not be opened.')
418419

419420
# Create the directory and ensure the config file now works
420-
os.mkdir(new_data_dir)
421+
new_data_dir.mkdir()
421422
self.start_node(0, [f'-conf={conf_file}'])
422423
self.stop_node(0)
423-
assert os.path.exists(os.path.join(new_data_dir, self.chain, 'blocks'))
424+
assert (new_data_dir / self.chain / 'blocks').exists()
424425

425426
# Ensure command line argument overrides datadir in conf
426-
os.mkdir(new_data_dir_2)
427-
self.nodes[0].datadir = new_data_dir_2
427+
new_data_dir_2.mkdir()
428+
self.nodes[0].datadir_path = new_data_dir_2
428429
self.start_node(0, [f'-datadir={new_data_dir_2}', f'-conf={conf_file}'])
429-
assert os.path.exists(os.path.join(new_data_dir_2, self.chain, 'blocks'))
430+
assert (new_data_dir_2 / self.chain / 'blocks').exists()
430431

431432

432433
if __name__ == '__main__':

test/functional/feature_filelock.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def run_test(self):
2828

2929
self.log.info("Check that we can't start a second bitcoind instance using the same datadir")
3030
expected_msg = f"Error: Cannot obtain a lock on data directory {datadir}. {self.config['environment']['PACKAGE_NAME']} is probably already running."
31-
self.nodes[1].assert_start_raises_init_error(extra_args=[f'-datadir={self.nodes[0].datadir}', '-noserver'], expected_msg=expected_msg)
31+
self.nodes[1].assert_start_raises_init_error(extra_args=[f'-datadir={self.nodes[0].datadir_path}', '-noserver'], expected_msg=expected_msg)
3232

3333
if self.is_wallet_compiled():
3434
def check_wallet_filelock(descriptors):

test/functional/feature_loadblock.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
in contrib/linearize.
1111
"""
1212

13-
import os
13+
from pathlib import Path
1414
import subprocess
1515
import sys
1616
import tempfile
@@ -32,10 +32,10 @@ def run_test(self):
3232
self.generate(self.nodes[0], COINBASE_MATURITY, sync_fun=self.no_op)
3333

3434
# Parsing the url of our node to get settings for config file
35-
data_dir = self.nodes[0].datadir
35+
data_dir = self.nodes[0].datadir_path
3636
node_url = urllib.parse.urlparse(self.nodes[0].url)
37-
cfg_file = os.path.join(data_dir, "linearize.cfg")
38-
bootstrap_file = os.path.join(self.options.tmpdir, "bootstrap.dat")
37+
cfg_file = data_dir / "linearize.cfg"
38+
bootstrap_file = Path(self.options.tmpdir) / "bootstrap.dat"
3939
genesis_block = self.nodes[0].getblockhash(0)
4040
blocks_dir = self.nodes[0].blocks_path
4141
hash_list = tempfile.NamedTemporaryFile(dir=data_dir,
@@ -58,16 +58,16 @@ def run_test(self):
5858
cfg.write(f"hashlist={hash_list.name}\n")
5959

6060
base_dir = self.config["environment"]["SRCDIR"]
61-
linearize_dir = os.path.join(base_dir, "contrib", "linearize")
61+
linearize_dir = Path(base_dir) / "contrib" / "linearize"
6262

6363
self.log.info("Run linearization of block hashes")
64-
linearize_hashes_file = os.path.join(linearize_dir, "linearize-hashes.py")
64+
linearize_hashes_file = linearize_dir / "linearize-hashes.py"
6565
subprocess.run([sys.executable, linearize_hashes_file, cfg_file],
6666
stdout=hash_list,
6767
check=True)
6868

6969
self.log.info("Run linearization of block data")
70-
linearize_data_file = os.path.join(linearize_dir, "linearize-data.py")
70+
linearize_data_file = linearize_dir / "linearize-data.py"
7171
subprocess.run([sys.executable, linearize_data_file, cfg_file],
7272
check=True)
7373

test/functional/feature_settings.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import json
88

9-
from pathlib import Path
109

1110
from test_framework.test_framework import BitcoinTestFramework
1211
from test_framework.test_node import ErrorMatch
@@ -21,8 +20,8 @@ def set_test_params(self):
2120

2221
def run_test(self):
2322
node, = self.nodes
24-
settings = Path(node.chain_path, "settings.json")
25-
conf = Path(node.datadir, "bitcoin.conf")
23+
settings = node.chain_path / "settings.json"
24+
conf = node.datadir_path / "bitcoin.conf"
2625

2726
# Assert empty settings file was created
2827
self.stop_node(0)
@@ -79,7 +78,7 @@ def run_test(self):
7978
self.stop_node(0)
8079

8180
# Test alternate settings path
82-
altsettings = Path(node.datadir, "altsettings.json")
81+
altsettings = node.datadir_path / "altsettings.json"
8382
with altsettings.open("w") as fp:
8483
fp.write('{"key": "value"}')
8584
with node.assert_debug_log(expected_msgs=['Setting file arg: key = "value"']):

test/functional/interface_bitcoin_cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def run_test(self):
9494
assert_equal(self.nodes[0].cli("-named", "echo", "arg0=0", "arg1=1", "arg2=2", "arg1=3").send_cli(), ['0', '3', '2'])
9595
assert_raises_rpc_error(-8, "Parameter args specified multiple times", self.nodes[0].cli("-named", "echo", "args=[0,1,2,3]", "4", "5", "6", ).send_cli)
9696

97-
user, password = get_auth_cookie(self.nodes[0].datadir, self.chain)
97+
user, password = get_auth_cookie(self.nodes[0].datadir_path, self.chain)
9898

9999
self.log.info("Test -stdinrpcpass option")
100100
assert_equal(BLOCKS, self.nodes[0].cli(f'-rpcuser={user}', '-stdinrpcpass', input=password).getblockcount())

test/functional/rpc_bind.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def run_allowip_test(self, allow_ips, rpchost, rpcport):
5656
self.nodes[0].rpchost = None
5757
self.start_nodes([node_args])
5858
# connect to node through non-loopback interface
59-
node = get_rpc_proxy(rpc_url(self.nodes[0].datadir, 0, self.chain, "%s:%d" % (rpchost, rpcport)), 0, coveragedir=self.options.coveragedir)
59+
node = get_rpc_proxy(rpc_url(self.nodes[0].datadir_path, 0, self.chain, "%s:%d" % (rpchost, rpcport)), 0, coveragedir=self.options.coveragedir)
6060
node.getnetworkinfo()
6161
self.stop_nodes()
6262

test/functional/rpc_dumptxoutset.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
55
"""Test the generation of UTXO snapshots using `dumptxoutset`.
66
"""
7-
from pathlib import Path
87

98
from test_framework.blocktools import COINBASE_MATURITY
109
from test_framework.test_framework import BitcoinTestFramework
@@ -29,7 +28,7 @@ def run_test(self):
2928

3029
FILENAME = 'txoutset.dat'
3130
out = node.dumptxoutset(FILENAME)
32-
expected_path = Path(node.datadir) / self.chain / FILENAME
31+
expected_path = node.datadir_path / self.chain / FILENAME
3332

3433
assert expected_path.is_file()
3534

test/functional/test_framework/test_framework.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,5 +1006,5 @@ def is_bdb_compiled(self):
10061006
return self.config["components"].getboolean("USE_BDB")
10071007

10081008
def has_blockfile(self, node, filenum: str):
1009-
blocksdir = os.path.join(node.datadir, self.chain, 'blocks', '')
1010-
return os.path.isfile(os.path.join(blocksdir, f"blk{filenum}.dat"))
1009+
blocksdir = node.datadir_path / self.chain / 'blocks'
1010+
return (blocksdir / f"blk{filenum}.dat").is_file()

0 commit comments

Comments
 (0)