Skip to content

Commit

Permalink
Refs #34118 -- Used delete_on_close argument of tempfile.NamedTempora…
Browse files Browse the repository at this point in the history
…ryFile 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.
  • Loading branch information
felixxm committed Mar 2, 2023
1 parent ef00d6e commit 0d6312a
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 43 deletions.
91 changes: 48 additions & 43 deletions django/core/files/temp.py
Expand Up @@ -18,8 +18,10 @@

import os
import tempfile
from functools import partial

from django.core.files.utils import FileProxyMixin
from django.utils.version import PY312

__all__ = (
"NamedTemporaryFile",
Expand All @@ -28,49 +30,52 @@


if os.name == "nt":

class TemporaryFile(FileProxyMixin):
"""
Temporary file object constructor that supports reopening of the
temporary file in Windows.
Unlike tempfile.NamedTemporaryFile from the standard library,
__init__() doesn't support the 'delete', 'buffering', 'encoding', or
'newline' keyword arguments.
"""

def __init__(self, mode="w+b", bufsize=-1, suffix="", prefix="", dir=None):
fd, name = tempfile.mkstemp(suffix=suffix, prefix=prefix, dir=dir)
self.name = name
self.file = os.fdopen(fd, mode, bufsize)
self.close_called = False

# Because close can be called during shutdown
# we need to cache os.unlink and access it
# as self.unlink only
unlink = os.unlink

def close(self):
if not self.close_called:
self.close_called = True
try:
self.file.close()
except OSError:
pass
try:
self.unlink(self.name)
except OSError:
pass

def __del__(self):
self.close()

def __enter__(self):
self.file.__enter__()
return self

def __exit__(self, exc, value, tb):
self.file.__exit__(exc, value, tb)
if PY312:
NamedTemporaryFile = partial(tempfile.NamedTemporaryFile, delete_on_close=False)
else:
# TODO: Remove when dropping support for PY311.
class TemporaryFile(FileProxyMixin):
"""
Temporary file object constructor that supports reopening of the
temporary file in Windows.
Unlike tempfile.NamedTemporaryFile from the standard library,
__init__() doesn't support the 'delete', 'buffering', 'encoding', or
'newline' keyword arguments.
"""

def __init__(self, mode="w+b", bufsize=-1, suffix="", prefix="", dir=None):
fd, name = tempfile.mkstemp(suffix=suffix, prefix=prefix, dir=dir)
self.name = name
self.file = os.fdopen(fd, mode, bufsize)
self.close_called = False

# Because close can be called during shutdown
# we need to cache os.unlink and access it
# as self.unlink only
unlink = os.unlink

def close(self):
if not self.close_called:
self.close_called = True
try:
self.file.close()
except OSError:
pass
try:
self.unlink(self.name)
except OSError:
pass

def __del__(self):
self.close()

def __enter__(self):
self.file.__enter__()
return self

def __exit__(self, exc, value, tb):
self.file.__exit__(exc, value, tb)

NamedTemporaryFile = TemporaryFile
else:
Expand Down
1 change: 1 addition & 0 deletions django/utils/version.py
Expand Up @@ -16,6 +16,7 @@
PY39 = sys.version_info >= (3, 9)
PY310 = sys.version_info >= (3, 10)
PY311 = sys.version_info >= (3, 11)
PY312 = sys.version_info >= (3, 12)


def get_version(version=None):
Expand Down

0 comments on commit 0d6312a

Please sign in to comment.