Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions Lib/tempfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@
if hasattr(_os, 'O_BINARY'):
_bin_openflags |= _os.O_BINARY

def _get_bin_openflags(mode):
if "r" in mode or "+" in mode:
return _bin_openflags
else:
return (_bin_openflags & ~_os.O_RDWR) | _os.O_WRONLY

if hasattr(_os, 'TMP_MAX'):
TMP_MAX = _os.TMP_MAX
else:
Expand Down Expand Up @@ -583,7 +589,7 @@ def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None,

prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir)

flags = _bin_openflags
flags = _get_bin_openflags(mode)

# Setting O_TEMPORARY in the flags causes the OS to delete
# the file when it is closed. This is only supported by Windows.
Expand Down Expand Up @@ -650,7 +656,7 @@ def TemporaryFile(mode='w+b', buffering=-1, encoding=None,

prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir)

flags = _bin_openflags
flags = _get_bin_openflags(mode)
if _O_TMPFILE_WORKS:
fd = None
def opener(*args):
Expand Down
27 changes: 23 additions & 4 deletions Lib/test/test_tempfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -940,14 +940,30 @@ def test_many(self):
# We test _TemporaryFileWrapper by testing NamedTemporaryFile.


class TestNamedTemporaryFile(BaseTestCase):
class BaseTemporaryFileTestCases:
def test_wronly_mode(self):
with mock.patch('os.open', wraps=os.open) as spy:
with self.do_create(mode='wb') as fileobj:
fileobj.write(b'abc')
fileobj.seek(0)
self.assertRaises(io.UnsupportedOperation, fileobj.read)
with self.assertRaises(OSError):
os.read(fileobj.fileno(), 1)

flags = spy.call_args[0][1]
self.assertEqual(flags & os.O_RDONLY, 0x0)
self.assertNotEqual(flags & os.O_RDWR, os.O_RDWR)
self.assertEqual(flags & os.O_WRONLY, os.O_WRONLY)
self.assertEqual(flags & os.O_EXCL, os.O_EXCL)

class TestNamedTemporaryFile(BaseTestCase, BaseTemporaryFileTestCases):
"""Test NamedTemporaryFile()."""

def do_create(self, dir=None, pre="", suf="", delete=True):
def do_create(self, dir=None, pre="", suf="", delete=True, mode='w+b'):
if dir is None:
dir = tempfile.gettempdir()
file = tempfile.NamedTemporaryFile(dir=dir, prefix=pre, suffix=suf,
delete=delete)
delete=delete, mode=mode)

self.nameCheck(file.name, dir, pre, suf)
return file
Expand Down Expand Up @@ -1519,9 +1535,12 @@ def test_class_getitem(self):

if tempfile.NamedTemporaryFile is not tempfile.TemporaryFile:

class TestTemporaryFile(BaseTestCase):
class TestTemporaryFile(BaseTestCase, BaseTemporaryFileTestCases):
"""Test TemporaryFile()."""

def do_create(self, *args, **kwargs):
return tempfile.TemporaryFile(*args, **kwargs)

def test_basic(self):
# TemporaryFile can create files
# No point in testing the name params - the file has no name.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Use the ``O_WRONLY`` flag instead of ``O_RDWR`` when opening file descriptors
for :class:`tempfile.TemporaryFile` and :class:`tempfile.NamedTemporaryFile`
objects created with a write-only mode).
Loading