Skip to content

Commit a95a8da

Browse files
committed
Refs #34118 -- Used delete_on_close argument of tempfile.NamedTemporaryFile on Windows and Python 3.12.
delete_on_close is available in Python 3.12: - python/cpython#58451 - python/cpython#97015 so we don't need a custom NamedTemporaryFile implementation anymore.
1 parent 56e5ea8 commit a95a8da

File tree

2 files changed

+51
-45
lines changed

2 files changed

+51
-45
lines changed

django/core/files/temp.py

Lines changed: 50 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818

1919
import os
2020
import tempfile
21+
from functools import partial
2122

2223
from django.core.files.utils import FileProxyMixin
24+
from django.utils.version import PY312
2325

2426
__all__ = (
2527
"NamedTemporaryFile",
@@ -28,51 +30,54 @@
2830

2931

3032
if os.name == "nt":
31-
32-
class TemporaryFile(FileProxyMixin):
33-
"""
34-
Temporary file object constructor that supports reopening of the
35-
temporary file in Windows.
36-
37-
Unlike tempfile.NamedTemporaryFile from the standard library,
38-
__init__() doesn't support the 'delete', 'buffering', 'encoding', or
39-
'newline' keyword arguments.
40-
"""
41-
42-
def __init__(self, mode="w+b", bufsize=-1, suffix="", prefix="", dir=None):
43-
fd, name = tempfile.mkstemp(suffix=suffix, prefix=prefix, dir=dir)
44-
self.name = name
45-
self.file = os.fdopen(fd, mode, bufsize)
46-
self.close_called = False
47-
48-
# Because close can be called during shutdown
49-
# we need to cache os.unlink and access it
50-
# as self.unlink only
51-
unlink = os.unlink
52-
53-
def close(self):
54-
if not self.close_called:
55-
self.close_called = True
56-
try:
57-
self.file.close()
58-
except OSError:
59-
pass
60-
try:
61-
self.unlink(self.name)
62-
except OSError:
63-
pass
64-
65-
def __del__(self):
66-
self.close()
67-
68-
def __enter__(self):
69-
self.file.__enter__()
70-
return self
71-
72-
def __exit__(self, exc, value, tb):
73-
self.file.__exit__(exc, value, tb)
74-
75-
NamedTemporaryFile = TemporaryFile
33+
if PY312:
34+
NamedTemporaryFile = partial(tempfile.NamedTemporaryFile, delete_on_close=False)
35+
else:
36+
# TODO: Remove when dropping support for PY311.
37+
class TemporaryFile(FileProxyMixin):
38+
"""
39+
Temporary file object constructor that supports reopening of the
40+
temporary file in Windows.
41+
42+
Unlike tempfile.NamedTemporaryFile from the standard library,
43+
__init__() doesn't support the 'delete', 'buffering', 'encoding', or
44+
'newline' keyword arguments.
45+
"""
46+
47+
def __init__(self, mode="w+b", bufsize=-1, suffix="", prefix="", dir=None):
48+
fd, name = tempfile.mkstemp(suffix=suffix, prefix=prefix, dir=dir)
49+
self.name = name
50+
self.file = os.fdopen(fd, mode, bufsize)
51+
self.close_called = False
52+
53+
# Because close can be called during shutdown
54+
# we need to cache os.unlink and access it
55+
# as self.unlink only
56+
unlink = os.unlink
57+
58+
def close(self):
59+
if not self.close_called:
60+
self.close_called = True
61+
try:
62+
self.file.close()
63+
except OSError:
64+
pass
65+
try:
66+
self.unlink(self.name)
67+
except OSError:
68+
pass
69+
70+
def __del__(self):
71+
self.close()
72+
73+
def __enter__(self):
74+
self.file.__enter__()
75+
return self
76+
77+
def __exit__(self, exc, value, tb):
78+
self.file.__exit__(exc, value, tb)
79+
80+
NamedTemporaryFile = TemporaryFile
7681
else:
7782
NamedTemporaryFile = tempfile.NamedTemporaryFile
7883

django/utils/version.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
PY39 = sys.version_info >= (3, 9)
1717
PY310 = sys.version_info >= (3, 10)
1818
PY311 = sys.version_info >= (3, 11)
19+
PY312 = sys.version_info >= (3, 12)
1920

2021

2122
def get_version(version=None):

0 commit comments

Comments
 (0)