Skip to content

Commit bed3f8a

Browse files
Fixed bug with NamedTemporaryFile on Windows (#4)
1 parent 3e152c2 commit bed3f8a

File tree

1 file changed

+39
-20
lines changed

1 file changed

+39
-20
lines changed

xtarfile/zstd.py

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from contextlib import contextmanager
22
from tarfile import open as tarfile_open
33
from tempfile import NamedTemporaryFile
4+
from os import remove as os_remove
45

56
try:
67
import zstandard
@@ -14,29 +15,47 @@ def __init__(self, **kwargs):
1415

1516
@contextmanager
1617
def read(self, path: str, mode: str):
17-
with NamedTemporaryFile() as decompressed:
18-
with open(path, 'rb') as compressed:
19-
zstd = zstandard.ZstdDecompressor(**self.zstd_kwargs)
20-
zstd.copy_stream(compressed, decompressed)
21-
decompressed.seek(0)
22-
archive = tarfile_open(mode=mode, fileobj=decompressed)
23-
try:
24-
yield archive
25-
finally:
26-
archive.close()
18+
try:
19+
with NamedTemporaryFile(delete=False) as decompressed:
20+
with open(path, 'rb') as compressed:
21+
zstd = zstandard.ZstdDecompressor(**self.zstd_kwargs)
22+
zstd.copy_stream(compressed, decompressed)
23+
decompressed.seek(0)
24+
archive = tarfile_open(mode=mode, fileobj=decompressed)
25+
try:
26+
yield archive
27+
finally:
28+
archive.close()
29+
finally:
30+
# We delete it manually because otherwise on Windows
31+
# it gets deleted before we move it to the output file location.
32+
# This is because on Windows, file handles with the O_TEMPORARY
33+
# flag (which is set if we pass `delete=True`) are deleted as
34+
# soon as they're closed.
35+
decompressed.close()
36+
os_remove(decompressed.name)
2737

2838
@contextmanager
2939
def write(self, path: str, mode: str):
30-
with NamedTemporaryFile() as decompressed:
31-
archive = tarfile_open(decompressed.name, mode=mode)
32-
try:
33-
yield archive
34-
finally:
35-
archive.close()
36-
decompressed.seek(0)
37-
with open(path, 'wb') as compressed:
38-
zstd = zstandard.ZstdCompressor(**self.zstd_kwargs)
39-
zstd.copy_stream(decompressed, compressed)
40+
try:
41+
with NamedTemporaryFile(delete=False) as decompressed:
42+
archive = tarfile_open(decompressed.name, mode=mode)
43+
try:
44+
yield archive
45+
finally:
46+
archive.close()
47+
decompressed.seek(0)
48+
with open(path, 'wb') as compressed:
49+
zstd = zstandard.ZstdCompressor(**self.zstd_kwargs)
50+
zstd.copy_stream(decompressed, compressed)
51+
finally:
52+
# We delete it manually because otherwise on Windows
53+
# it gets deleted before we move it to the output file location.
54+
# This is because on Windows, file handles with the O_TEMPORARY
55+
# flag (which is set if we pass `delete=True`) are deleted as
56+
# soon as they're closed.
57+
decompressed.close()
58+
os_remove(decompressed.name)
4059

4160

4261
if zstandard is None:

0 commit comments

Comments
 (0)