Skip to content

Commit 1adfccb

Browse files
committed
Removed tempfile from Patcher
- removed fake_tempfile - removed tests only relevant for fake implementation - changed remaining tests to work with real tempfile - configure Patcher to work with tempfile, create temp dir in setUpPyfakefs() - added hack to fix problem with cached os functions in Patcher (Posix only) - added support for O_TEMPORARY flag to os.open (Windows only) - added support for low level exclusive mode in Python 2 - added current pypy version to travis - fixes #191
1 parent fd6fc05 commit 1adfccb

9 files changed

+106
-568
lines changed

.travis.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ python:
2222
- "3.4"
2323
- "3.5"
2424
- "3.6"
25-
- "nightly" # points to 3.7-dev
25+
- "3.7-dev"
2626
- "pypy"
2727
- "pypy3"
28+
- "pypy-5.3.1"
2829

2930
install:
3031
- pip install -r requirements.txt

fake_filesystem_test.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -2571,6 +2571,14 @@ def testLowLevelOpenTruncate(self):
25712571
self.assertEqual(4, self.os.write(file_des, b'test'))
25722572
self.assertEqual(b'test', file_obj.byte_contents)
25732573

2574+
@unittest.skipIf(not TestCase.is_windows, 'O_TEMPORARY only present in Windows')
2575+
def testLowLevelTempFile(self):
2576+
file_name = 'foo'
2577+
fd = self.os.open(file_name, os.O_CREAT | os.O_RDWR | os.O_TEMPORARY)
2578+
self.assertTrue(self.filesystem.Exists(file_name))
2579+
self.os.close(fd)
2580+
self.assertFalse(self.filesystem.Exists(file_name))
2581+
25742582
def testLowLevelOpenAppend(self):
25752583
file_path = 'file1'
25762584
file_obj = self.filesystem.CreateFile(file_path, contents=b'contents',
@@ -5278,7 +5286,7 @@ def testAddExistingRealDirectoryReadOnly(self):
52785286
self.assertTrue(self.filesystem.Exists(os.path.join(real_dir_path, 'fake_filesystem.py')))
52795287
self.assertTrue(self.filesystem.Exists(os.path.join(real_dir_path, 'fake_pathlib.py')))
52805288

5281-
file_path = os.path.join(real_dir_path, 'fake_tempfile.py')
5289+
file_path = os.path.join(real_dir_path, 'fake_filesystem_shutil.py')
52825290
fake_file = self.filesystem.ResolveObject(file_path)
52835291
self.checkFakeFileStat(fake_file, file_path)
52845292
self.checkReadOnlyFile(fake_file, file_path)

fake_filesystem_unittest_test.py

+2-18
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import os
2424
import glob
2525
import shutil
26-
import tempfile
2726
import sys
2827

2928
from import_as_example import check_if_exists
@@ -115,20 +114,6 @@ def test_shutil(self):
115114
shutil.rmtree('/test/dir1')
116115
self.assertFalse(self.fs.Exists('/test/dir1'))
117116

118-
def test_tempfile(self):
119-
"""Fake tempfile module is bound"""
120-
with tempfile.NamedTemporaryFile() as tf:
121-
tf.write(b'Temporary file contents\n')
122-
name = tf.name
123-
self.assertTrue(self.fs.Exists(tf.name))
124-
125-
@unittest.skipIf(sys.version_info < (3, 0), "TemporaryDirectory new in Python3")
126-
def test_tempdirectory(self):
127-
"""Fake TemporaryDirectory class is bound"""
128-
with tempfile.TemporaryDirectory() as td:
129-
with open('%s/fake_file.txt' % td, 'w') as f:
130-
self.assertTrue(self.fs.Exists(td))
131-
132117
@unittest.skipIf(sys.version_info < (3, 4), "pathlib new in Python 3.4")
133118
def test_fakepathlib(self):
134119
with pathlib.Path('/fake_file.txt') as p:
@@ -174,7 +159,6 @@ def testAttributes(self):
174159
self.assertEqual(module_with_attributes.path, 'path attribute value')
175160
self.assertEqual(module_with_attributes.pathlib, 'pathlib attribute value')
176161
self.assertEqual(module_with_attributes.shutil, 'shutil attribute value')
177-
self.assertEqual(module_with_attributes.tempfile, 'tempfile attribute value')
178162
self.assertEqual(module_with_attributes.io, 'io attribute value')
179163

180164

@@ -226,9 +210,9 @@ def testCopyRealFile(self):
226210
real_file_path = __file__
227211
fake_file = self.copyRealFile(real_file_path)
228212

229-
self.assertTrue('class TestCopyRealFile(TestPyfakefsUnittestBase)' in self.real_string_contents,
213+
self.assertTrue('class TestCopyOrAddRealFile(TestPyfakefsUnittestBase)' in self.real_string_contents,
230214
'Verify real file string contents')
231-
self.assertTrue(b'class TestCopyRealFile(TestPyfakefsUnittestBase)' in self.real_byte_contents,
215+
self.assertTrue(b'class TestCopyOrAddRealFile(TestPyfakefsUnittestBase)' in self.real_byte_contents,
232216
'Verify real file byte contents')
233217

234218
# note that real_string_contents may differ to fake_file.contents due to newline conversions in open()

fake_filesystem_vs_real_test.py

-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import os # @UnusedImport
2222
import os.path
2323
import shutil
24-
import sys
2524
import tempfile
2625
import time
2726
import sys

fake_tempfile_test.py

+36-144
Original file line numberDiff line numberDiff line change
@@ -14,197 +14,89 @@
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616

17-
"""Tests for the fake_tempfile module."""
18-
19-
# pylint: disable-all
17+
"""Tests that ensure that the `tempfile` module works with `fake_filesystem`
18+
if using `Patcher` (via `fake_filesystem_unittest`).
19+
"""
2020

21+
import os
2122
import stat
2223
import sys
2324

25+
import tempfile
26+
2427
if sys.version_info < (2, 7):
2528
import unittest2 as unittest
2629
else:
2730
import unittest
2831

29-
try:
30-
import StringIO as io # pylint: disable-msg=C6204
31-
except ImportError:
32-
import io # pylint: disable-msg=C6204
33-
34-
from pyfakefs import fake_filesystem
35-
from pyfakefs import fake_tempfile
36-
37-
38-
class FakeLogging(object):
39-
"""Fake logging object for testGettempprefix."""
40-
41-
def __init__(self, test_case):
42-
self._message = None
43-
self._test_case = test_case
44-
45-
# pylint: disable-msg=C6409
46-
def error(self, message):
47-
if self._message is not None:
48-
self.FailOnMessage(message)
49-
self._message = message
32+
from pyfakefs import fake_filesystem_unittest
5033

51-
def FailOnMessage(self, message):
52-
self._test_case.fail('Unexpected message received: %s' % message)
5334

54-
warn = FailOnMessage
55-
info = FailOnMessage
56-
debug = FailOnMessage
57-
fatal = FailOnMessage
58-
59-
def message(self):
60-
return self._message
61-
62-
63-
class FakeTempfileModuleTest(unittest.TestCase):
64-
"""Test the 'tempfile' module mock."""
35+
class FakeTempfileModuleTest(fake_filesystem_unittest.TestCase):
36+
"""Test the 'tempfile' module with the fake file system."""
6537

6638
def setUp(self):
67-
self.filesystem = fake_filesystem.FakeFilesystem(path_separator='/')
68-
self.os = fake_filesystem.FakeOsModule(self.filesystem)
69-
self.tempfile = fake_tempfile.FakeTempfileModule(self.filesystem)
70-
self.orig_logging = fake_tempfile.logging
71-
self.fake_logging = FakeLogging(self)
72-
fake_tempfile.logging = self.fake_logging
73-
74-
def tearDown(self):
75-
fake_tempfile.logging = self.orig_logging
76-
77-
def testTempFilename(self):
78-
# pylint: disable-msg=C6002
79-
# TODO: test that tempdir is init'ed
80-
filename_a = self.tempfile._TempFilename()
81-
# expect /tmp/tmp######
82-
self.assertTrue(filename_a.startswith('/tmp/tmp'))
83-
self.assertLess(len('/tmp/tmpA'), len(filename_a))
84-
85-
# see that random part changes
86-
filename_b = self.tempfile._TempFilename()
87-
self.assertTrue(filename_b.startswith('/tmp/tmp'))
88-
self.assertLess(len('/tmp/tmpB'), len(filename_a))
89-
self.assertNotEqual(filename_a, filename_b)
90-
91-
def testTempFilenameSuffix(self):
92-
"""test tempfile._TempFilename(suffix=)."""
93-
filename = self.tempfile._TempFilename(suffix='.suffix')
94-
self.assertTrue(filename.startswith('/tmp/tmp'))
95-
self.assertTrue(filename.endswith('.suffix'))
96-
self.assertLess(len('/tmp/tmpX.suffix'), len(filename))
97-
98-
def testTempFilenamePrefix(self):
99-
"""test tempfile._TempFilename(prefix=)."""
100-
filename = self.tempfile._TempFilename(prefix='prefix.')
101-
self.assertTrue(filename.startswith('/tmp/prefix.'))
102-
self.assertLess(len('/tmp/prefix.X'), len(filename))
103-
104-
def testTempFilenameDir(self):
105-
"""test tempfile._TempFilename(dir=)."""
106-
filename = self.tempfile._TempFilename(directory='/dir')
107-
self.assertTrue(filename.startswith('/dir/tmp'))
108-
self.assertLess(len('/dir/tmpX'), len(filename))
109-
110-
def testTemporaryFile(self):
111-
obj = self.tempfile.TemporaryFile()
112-
self.assertEqual('<fdopen>', obj.name)
113-
self.assertTrue(isinstance(obj, io.StringIO))
39+
self.setUpPyfakefs()
11440

11541
def testNamedTemporaryFile(self):
116-
obj = self.tempfile.NamedTemporaryFile()
117-
created_filenames = self.tempfile.FakeReturnedMktempValues()
118-
self.assertEqual(created_filenames[0], obj.name)
119-
self.assertTrue(self.filesystem.GetObject(obj.name))
42+
obj = tempfile.NamedTemporaryFile()
43+
self.assertTrue(self.fs.GetObject(obj.name))
12044
obj.close()
121-
self.assertRaises(IOError, self.filesystem.GetObject, created_filenames[0])
45+
self.assertRaises(IOError, self.fs.GetObject, obj.name)
12246

12347
def testNamedTemporaryFileNoDelete(self):
124-
obj = self.tempfile.NamedTemporaryFile(delete=False)
48+
obj = tempfile.NamedTemporaryFile(delete=False)
12549
obj.write(b'foo')
12650
obj.close()
127-
file_obj = self.filesystem.GetObject(obj.name)
51+
file_obj = self.fs.GetObject(obj.name)
12852
contents = file_obj.contents
12953
self.assertEqual('foo', contents)
130-
obj = self.tempfile.NamedTemporaryFile(mode='w', delete=False)
54+
obj = tempfile.NamedTemporaryFile(mode='w', delete=False)
13155
obj.write('foo')
13256
obj.close()
133-
file_obj = self.filesystem.GetObject(obj.name)
57+
file_obj = self.fs.GetObject(obj.name)
13458
self.assertEqual('foo', file_obj.contents)
13559

13660
def testMkstemp(self):
137-
next_fd = len(self.filesystem.open_files)
138-
temporary = self.tempfile.mkstemp()
61+
next_fd = len(self.fs.open_files)
62+
temporary = tempfile.mkstemp()
13963
self.assertEqual(2, len(temporary))
140-
self.assertTrue(temporary[1].startswith('/tmp/tmp'))
141-
created_filenames = self.tempfile.FakeReturnedMktempValues()
64+
self.assertTrue(temporary[1].startswith(os.path.join(tempfile.gettempdir(), 'tmp')))
14265
self.assertEqual(next_fd, temporary[0])
143-
self.assertEqual(temporary[1], created_filenames[0])
144-
self.assertTrue(self.filesystem.Exists(temporary[1]))
145-
self.assertEqual(self.filesystem.GetObject(temporary[1]).st_mode,
66+
self.assertTrue(self.fs.Exists(temporary[1]))
67+
self.assertEqual(self.fs.GetObject(temporary[1]).st_mode,
14668
stat.S_IFREG | 0o600)
147-
fh = self.os.fdopen(temporary[0], 'w+b')
69+
fh = os.fdopen(temporary[0], 'w+b')
14870
self.assertEqual(temporary[0], fh.fileno())
14971

15072
def testMkstempDir(self):
15173
"""test tempfile.mkstemp(dir=)."""
15274
# expect fail: /dir does not exist
153-
self.assertRaises(OSError, self.tempfile.mkstemp, dir='/dir')
75+
self.assertRaises(OSError, tempfile.mkstemp, dir='/dir')
15476
# expect pass: /dir exists
155-
self.filesystem.CreateDirectory('/dir')
156-
next_fd = len(self.filesystem.open_files)
157-
temporary = self.tempfile.mkstemp(dir='/dir')
77+
self.fs.CreateDirectory('/dir')
78+
next_fd = len(self.fs.open_files)
79+
temporary = tempfile.mkstemp(dir='/dir')
15880
self.assertEqual(2, len(temporary))
15981
self.assertEqual(next_fd, temporary[0])
160-
self.assertTrue(temporary[1].startswith('/dir/tmp'))
161-
created_filenames = self.tempfile.FakeReturnedMktempValues()
162-
self.assertEqual(temporary[1], created_filenames[0])
163-
self.assertTrue(self.filesystem.Exists(temporary[1]))
164-
self.assertEqual(self.filesystem.GetObject(temporary[1]).st_mode,
82+
self.assertTrue(temporary[1].startswith(os.path.join(os.sep, 'dir', 'tmp')))
83+
self.assertTrue(self.fs.Exists(temporary[1]))
84+
self.assertEqual(self.fs.GetObject(temporary[1]).st_mode,
16585
stat.S_IFREG | 0o600)
166-
# pylint: disable-msg=C6002
167-
# TODO: add a test that /dir is actually writable.
16886

16987
def testMkdtemp(self):
170-
dirname = self.tempfile.mkdtemp()
88+
dirname = tempfile.mkdtemp()
17189
self.assertTrue(dirname)
172-
created_filenames = self.tempfile.FakeReturnedMktempValues()
173-
self.assertEqual(dirname, created_filenames[0])
174-
self.assertTrue(self.filesystem.Exists(dirname))
175-
self.assertEqual(self.filesystem.GetObject(dirname).st_mode,
90+
self.assertTrue(self.fs.Exists(dirname))
91+
self.assertEqual(self.fs.GetObject(dirname).st_mode,
17692
stat.S_IFDIR | 0o700)
17793

178-
def testGettempdir(self):
179-
self.assertEqual(None, self.tempfile.tempdir)
180-
self.assertEqual('/tmp', self.tempfile.gettempdir())
181-
self.assertEqual('/tmp', self.tempfile.tempdir)
182-
183-
def testGettempprefix(self):
184-
"""test tempfile.gettempprefix() and the tempfile.template setter."""
185-
self.assertEqual('tmp', self.tempfile.gettempprefix())
186-
# set and verify
187-
self.tempfile.template = 'strung'
188-
self.assertEqual('strung', self.tempfile.gettempprefix())
189-
self.assertEqual('tempfile.template= is a NOP in python2.4',
190-
self.fake_logging.message())
191-
192-
def testMktemp(self):
193-
self.assertRaises(NotImplementedError, self.tempfile.mktemp)
194-
195-
def testTemplateGet(self):
196-
"""verify tempfile.template still unimplemented."""
197-
self.assertRaises(NotImplementedError, getattr,
198-
self.tempfile, 'template')
199-
20094
@unittest.skipIf(sys.version_info < (3, 0), "TemporaryDirectory showed up in 3")
20195
def testTemporaryDirectory(self):
202-
with self.tempfile.TemporaryDirectory() as tmpdir:
96+
with tempfile.TemporaryDirectory() as tmpdir:
20397
self.assertTrue(tmpdir)
204-
created_filenames = self.tempfile.FakeReturnedMktempValues()
205-
self.assertEqual(tmpdir, created_filenames[0])
206-
self.assertTrue(self.filesystem.Exists(tmpdir))
207-
self.assertEqual(self.filesystem.GetObject(tmpdir).st_mode,
98+
self.assertTrue(self.fs.Exists(tmpdir))
99+
self.assertEqual(self.fs.GetObject(tmpdir).st_mode,
208100
stat.S_IFDIR | 0o700)
209101

210102

fixtures/module_with_attributes.py

-1
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,4 @@
2727
path = 'path attribute value'
2828
pathlib = 'pathlib attribute value'
2929
shutil = 'shutil attribute value'
30-
tempfile = 'tempfile attribute value'
3130
io = 'io attribute value'

pyfakefs/fake_filesystem.py

+15-7
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,9 @@
131131
'a+': (False, True, True, False, True, False),
132132
'w!': (False, False, True, False, False, False),
133133
'w!+': (False, True, True, False, False, False),
134+
'x': (False, False, True, False, False, True),
135+
'x+': (False, True, True, False, False, True),
134136
}
135-
if sys.version_info >= (3, 3):
136-
_OPEN_MODE_MAP['x'] = (False, False, True, False, False, True)
137-
_OPEN_MODE_MAP['x+'] = (False, True, True, False, False, True)
138137

139138
if sys.platform.startswith('linux'):
140139
# on newer Linux system, the default maximum recursion depth is 40
@@ -3190,7 +3189,12 @@ def open(self, file_path, flags, mode=None, dir_fd=None):
31903189

31913190
# low level open is always binary
31923191
str_flags += 'b'
3193-
fake_file = FakeFileOpen(self.filesystem, low_level=True)(file_path, str_flags)
3192+
delete_on_close = False
3193+
if hasattr(os, 'O_TEMPORARY'):
3194+
delete_on_close = flags & os.O_TEMPORARY == os.O_TEMPORARY
3195+
fake_file = FakeFileOpen(self.filesystem,
3196+
delete_on_close=delete_on_close,
3197+
low_level=True)(file_path, str_flags)
31943198
if mode:
31953199
self.chmod(file_path, mode)
31963200
return fake_file.fileno()
@@ -4026,7 +4030,7 @@ def __init__(self, file_object, file_path, update=False, read=False, append=Fals
40264030
if delete_on_close:
40274031
assert filesystem, 'delete_on_close=True requires filesystem'
40284032
self._filesystem = filesystem
4029-
self._delete_on_close = delete_on_close
4033+
self.delete_on_close = delete_on_close
40304034
# override, don't modify FakeFile.name, as FakeFilesystem expects
40314035
# it to be the file name only, no directories.
40324036
self.name = file_object.opened_as
@@ -4061,8 +4065,8 @@ def close(self):
40614065
self._file_object.SetContents(self._io.getvalue(), self._encoding)
40624066
if self._closefd:
40634067
self._filesystem.CloseOpenFile(self.filedes)
4064-
if self._delete_on_close:
4065-
self._filesystem.RemoveObject(self.name)
4068+
if self.delete_on_close:
4069+
self._filesystem.RemoveObject(self.GetObject().GetPath())
40664070

40674071
def flush(self):
40684072
"""Flush file contents to 'disk'."""
@@ -4323,6 +4327,8 @@ def Call(self, file_, mode='r', buffering=-1, encoding=None,
43234327

43244328
if mode not in _OPEN_MODE_MAP:
43254329
raise ValueError('Invalid mode: %r' % orig_modes)
4330+
if 'x' in mode and not self.low_level and sys.version_info < (3, 3):
4331+
raise ValueError('Exclusive mode not supported before Python 3.3')
43264332

43274333
must_exist, need_read, need_write, truncate, append, must_not_exist = _OPEN_MODE_MAP[mode]
43284334

@@ -4331,6 +4337,8 @@ def Call(self, file_, mode='r', buffering=-1, encoding=None,
43314337
# opening a file descriptor
43324338
if isinstance(file_, int):
43334339
filedes = file_
4340+
wrapper = self.filesystem.GetOpenFile(filedes)
4341+
self._delete_on_close = wrapper.delete_on_close
43344342
file_object = self.filesystem.GetOpenFile(filedes).GetObject()
43354343
file_path = file_object.name
43364344
else:

0 commit comments

Comments
 (0)