Skip to content

Commit 1ac971d

Browse files
committed
fix(fs): Fix utils.fs issues on Windows
- Avoid using checked-in fixtures for `Path.hexdigest` tests git automatically converts Unix-style line endings to Windows-style endings when checking out on a Windows platform. This changes the hash of text-mode binary files we use for testing `Path.hexdigest`. To avoid this, we simply write some data on-the fly during the test instead of relying on checked-in fixtures. - Close file handle in `temp_file` context manager `NamedTemporaryFile` actually opens the created file automatically. To be consistent with `temp_directory` and the rest of the Path class, we return a Path instead. This means we now have an inaccessible open file handle. Callers then usually re-open the file manually using the path, creating a second open file handle. This is not a problem on UNIX systems, as the same file can have multiple open handles from the same process - this is not the case on Windows however: https://docs.python.org/3.9/library/tempfile.html#tempfile.NamedTemporaryFile - Avoid some permissions issues
1 parent 7ffd638 commit 1ac971d

File tree

5 files changed

+30
-70
lines changed

5 files changed

+30
-70
lines changed

src/dda/utils/fs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ def temp_file(suffix: str = "") -> Generator[Path, None, None]:
214214
from tempfile import NamedTemporaryFile
215215

216216
with NamedTemporaryFile(suffix=suffix) as f:
217+
f.close() # NamedTemporaryFile returns a file descriptor, not a path. We close it as, on Windows, it is not possible to open a file descriptor twice.
217218
yield Path(f.name).resolve()
218219

219220

-64.1 KB
Binary file not shown.

tests/utils/fixtures/hash_files/dd_icon_white.svg

Lines changed: 0 additions & 39 deletions
This file was deleted.

tests/utils/fixtures/hash_files/lipsum.txt

Lines changed: 0 additions & 3 deletions
This file was deleted.

tests/utils/test_fs.py

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import pytest
1111

1212
from dda.types.hooks import dec_hook, enc_hook
13-
from dda.utils.fs import Path, temp_directory
13+
from dda.utils.fs import Path, temp_directory, temp_file
1414

1515

1616
class TestPath:
@@ -67,47 +67,48 @@ def test_encode_decode_windows(self, path_str):
6767
assert decoded_path == path
6868

6969
@pytest.mark.parametrize(
70-
("file", "hashes"),
70+
("data", "hashes"),
7171
[
7272
(
73-
"lipsum.txt",
73+
b"Lorem ipsum dolor sit amet, consectetur adipiscing elit. In aliquet felis in pretium aliquet. Ut ac laoreet quam. Vivamus velit.",
7474
{
75-
"sha256": "e921ca1908b2928951026a4f4aa39b4e0e45faa1ed35c6bec5d0a1172f749b19",
76-
"sha512": "39262feb3dddfbfe4fb0f6a7d62cc1e3a5956a8dc9f3f2cfe881ba86883800c66a5854839588193ca3cbf3d7a01f0adf32aafa568d5e8ca83f823070c4c12470",
77-
"blake2b": "dd89da4063a1b0725b5f9012a861c4a5dca904a648408d4c6b777b07bdc0294c8736d892ff6a1c0a6e3c58df4c4f6d91682e830f508380333478b11dd1d40e71",
75+
"sha256": "cfa2679987c09a6a650119bb403b7409097dde137fd5d6c5b73e1887ce2b1fa9",
76+
"sha512": "51799af49d7e298ae8ecc9d3cb8494ce1798bc30b8ec00bd94ba9b4dcdf1cf44fb3adf2ff4046543a50b0c8d480813895712b53561803dd482037d670ee92dbb",
77+
"blake2b": "4398d6c895645672abe343c4bcaa283adb7e35e534b1dc164a2426040ca74b4b285b5847f5fa86ce51aa84159a587cc5332cbeb8ceaa3b98c4f6fccdbc36df55",
7878
},
7979
),
8080
(
81-
"dd_icon_white.svg",
81+
b"Etiam eget imperdiet enim, vel blandit mauris. Cras dapibus nam.",
8282
{
83-
"sha256": "846d2ee9685255f043eb26f067bb01b1a1411790f0808b8b137fe2caed271b17",
84-
"sha512": "eb712138447228a52af1646ba24fedffa4d847d4759a3481cd233abea65fa82b6daa892d3ecebdfb2cecc62efa63577a68fbf58572e605afcfb99c1b16893b72",
85-
"blake2b": "89af50b94a061a28b76e6801a35c202dc1cb50a5d77cbb2f773c46a6834ac111fea717ddfd6758fd21669418fb8dcabc27d5438d5017b9bd614985c399196717",
83+
"sha256": "ef7f1b043a2b91c2900ead0091f1ac715a8e97f5bf4508cff3738ac11b711f03",
84+
"sha512": "21907a7f2c887c871a38919154916a81e2f3bb75dd26bbcde2d12c4c3d2c82eb83f94446196fcbdd35cad5bd9e17f3efafb2e2300949b0d93e18b5c54df1ab56",
85+
"blake2b": "3815deec2d01e0a7ca59fb3c7782f668d10ff04b3d0c3973db1f934f18d92ec24c3fc2aead937736144f0e65d29440520de68ce75d88e258db72b1062edb825c",
8686
},
8787
),
8888
(
89-
"dd_icon_white.png",
89+
b"Phasellus congue commodo erat quis eleifend. Nulla semper velit eget mauris ultricies laoreet.\n Sed orci tellus, venenatis vitae egestas vel, vehicula eget odio.",
9090
{
91-
"sha256": "b240ea6d9e70afe7a5241386c7d19ac00d1e62322dde29e5a86abd9b90834a42",
92-
"sha512": "dcbb45592b3ee64f136c9b81c0f119aeb03eb648ef4b906da48337d518bb9a9b370b420e5a95fdc8952946f08ac3795a4cae4b3b3ac9dfff97aa9c4bc3352ad9",
93-
"blake2b": "40c6b509cd6b3efe23038978ea3fedae62ec0fee2ffd264bcf1e64d6270140a145bc5a815a9ff17a82f01cdcc61ac09ad219f47e54c413c41e861f51c883f4da",
91+
"sha256": "4ca6c0ca071e0cfdab3f6aeea99f852d6b9e2981409ffffa7a8f88b1e951c605",
92+
"sha512": "c357c4eb2c8093774a807393fc19dcd980d8335c5d6e1d8b98bc1b8be2002a4c3f0d19b78f5d08290f8ec30f22951d3bff72c0ae8f0bfbe88429f9234ecb49d9",
93+
"blake2b": "12edd771bf10e018bf31896985a4ce36941127d80d1e738ad712e0e4717c04deb0fa98f1dad02126e903f370019d9168041240722dc821386f5ff4efce36dd63",
9494
},
9595
),
9696
],
9797
)
98-
def test_hexdigest(self, file, hashes):
99-
path = Path(__file__).parent / "fixtures" / "hash_files" / file
98+
def test_hexdigest(self, data, hashes):
10099
algos = hashes.keys()
101-
for algo in algos:
102-
# Try with the default buffer size
103-
digest = path.hexdigest(algorithm=algo)
104-
assert digest == hashes[algo]
105-
106-
# Try with another buffer size
107-
digest = path.hexdigest(algorithm=algo, buffer_size=8192)
108-
assert digest == hashes[algo]
109-
110-
def test_hexdigest_invalid_call(self):
100+
with temp_file(suffix=".txt") as path:
101+
path.write_atomic(data, "wb")
102+
for algo in algos:
103+
# Try with the default buffer size
104+
digest = path.hexdigest(algorithm=algo)
105+
assert digest == hashes[algo]
106+
107+
# Try with another buffer size
108+
digest = path.hexdigest(algorithm=algo, buffer_size=32)
109+
assert digest == hashes[algo]
110+
111+
def test_hexdigest_invalid_call(self, temp_dir):
111112
fake_algo = "not_a_real_algo"
112113
with pytest.raises(
113114
ValueError,
@@ -119,8 +120,8 @@ def test_hexdigest_invalid_call(self):
119120
with pytest.raises(FileNotFoundError):
120121
non_existing_path.hexdigest()
121122

122-
non_file_path = Path(__file__).parent
123-
with pytest.raises(IsADirectoryError):
123+
non_file_path = temp_dir
124+
with pytest.raises((IsADirectoryError, PermissionError)):
124125
non_file_path.hexdigest()
125126

126127

0 commit comments

Comments
 (0)