Commit 5ca1cba2 authored by Nick Coghlan's avatar Nick Coghlan

Backport relevant part of issue 2021 fix (r60695): Support with statement...

Backport relevant part of issue 2021 fix (r60695): Support with statement properly in tempfile.NamedTemporaryFile
parent 0b5c17a9
......@@ -378,17 +378,25 @@ class _TemporaryFileWrapper:
self.close_called = False
def __getattr__(self, name):
# Attribute lookups are delegated to the underlying file
# and cached for non-numeric results
# (i.e. methods are cached, closed and friends are not)
file = self.__dict__['file']
a = getattr(file, name)
if type(a) != type(0):
setattr(self, name, a)
return a
# The underlying __enter__ method returns the wrong object
# (self.file) so override it to return the wrapper
def __enter__(self):
self.file.__enter__()
return self
# NT provides delete-on-close as a primitive, so we don't need
# the wrapper to do anything special. We still use it so that
# file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
if _os.name != 'nt':
# Cache the unlinker so we don't get spurious errors at
# shutdown when the module-level "os" is None'd out. Note
# that this must be referenced as self.unlink, because the
......@@ -405,6 +413,14 @@ class _TemporaryFileWrapper:
def __del__(self):
self.close()
# Need to trap __exit__ as well to ensure the file gets
# deleted when used in a with statement
def __exit__(self, exc, value, tb):
result = self.file.__exit__(exc, value, tb)
self.close()
return result
def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="",
prefix=template, dir=None):
"""Create and return a temporary file.
......
# tempfile.py unit tests.
from __future__ import with_statement
import tempfile
import os
import sys
......@@ -298,7 +298,7 @@ class test__mkstemp_inner(TC):
# On Windows a spawn* /path/ with embedded spaces shouldn't be quoted,
# but an arg with embedded spaces should be decorated with double
# quotes on each end
if sys.platform in ('win32'):
if sys.platform in ('win32',):
decorated = '"%s"' % sys.executable
tester = '"%s"' % tester
else:
......@@ -601,7 +601,6 @@ class test_NamedTemporaryFile(TC):
def test_multiple_close(self):
# A NamedTemporaryFile can be closed many times without error
f = tempfile.NamedTemporaryFile()
f.write('abc\n')
f.close()
......@@ -611,6 +610,16 @@ class test_NamedTemporaryFile(TC):
except:
self.failOnException("close")
def test_context_manager(self):
# A NamedTemporaryFile can be used as a context manager
with tempfile.NamedTemporaryFile() as f:
self.failUnless(os.path.exists(f.name))
self.failIf(os.path.exists(f.name))
def use_closed():
with f:
pass
self.failUnlessRaises(ValueError, use_closed)
# How to test the mode and bufsize parameters?
test_classes.append(test_NamedTemporaryFile)
......
......@@ -83,6 +83,9 @@ Core and builtins
Library
-------
- #2021: Allow tempfile.NamedTemporaryFile to be used in with statements
by correctly supporting the context management protocol.
- Fixed _ctypes.COMError so that it must be called with exactly three
arguments, instances now have the hresult, text, and details
instance variables.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment