blob: 2b0ec46a1032761bb84412868351735fdd8897f3 [file] [log] [blame]
Guido van Rossum0e548712002-08-09 16:14:33 +00001# tempfile.py unit tests.
Tim Petersc57a2852001-10-29 21:46:08 +00002import tempfile
Serhiy Storchaka7451a722013-02-09 22:25:49 +02003import errno
Serhiy Storchakaf6b361e2013-02-13 00:35:30 +02004import io
Guido van Rossum0e548712002-08-09 16:14:33 +00005import os
Anthony Sottile370138b2019-09-09 08:54:34 -07006import pathlib
Guido van Rossum0e548712002-08-09 16:14:33 +00007import sys
8import re
Guido van Rossum0e548712002-08-09 16:14:33 +00009import warnings
Eli Benderskyaa04f9a2013-09-13 05:28:20 -070010import contextlib
Anthony Sottile8377cd42019-02-25 14:32:27 -080011import stat
Guido van Rossum48b069a2020-04-07 09:50:06 -070012import types
Antoine Pitrou17c93262013-12-21 22:14:56 +010013import weakref
Victor Stinner1f99f9d2014-03-25 09:18:04 +010014from unittest import mock
Tim Petersc57a2852001-10-29 21:46:08 +000015
Guido van Rossum0e548712002-08-09 16:14:33 +000016import unittest
Berker Peksagce643912015-05-06 06:33:17 +030017from test import support
Hai Shi0c4f0f32020-06-30 21:46:31 +080018from test.support import os_helper
Berker Peksagce643912015-05-06 06:33:17 +030019from test.support import script_helper
Hai Shi0c4f0f32020-06-30 21:46:31 +080020from test.support import warnings_helper
Guido van Rossum0e548712002-08-09 16:14:33 +000021
Fred Drake7633d232002-10-17 22:09:03 +000022
Guido van Rossum0e548712002-08-09 16:14:33 +000023has_textmode = (tempfile._text_openflags != tempfile._bin_openflags)
Guido van Rossum78741062002-08-17 11:41:01 +000024has_spawnl = hasattr(os, 'spawnl')
Guido van Rossum0e548712002-08-09 16:14:33 +000025
Neal Norwitz68ee0122002-08-16 19:28:59 +000026# TEST_FILES may need to be tweaked for systems depending on the maximum
27# number of files that can be opened at one time (see ulimit -n)
Victor Stinner9c3de4a2011-08-17 20:49:41 +020028if sys.platform.startswith('openbsd'):
Martin v. Löwis99968282004-09-15 06:02:54 +000029 TEST_FILES = 48
Jack Jansence921472003-01-08 16:30:34 +000030else:
31 TEST_FILES = 100
Neal Norwitz68ee0122002-08-16 19:28:59 +000032
Guido van Rossum0e548712002-08-09 16:14:33 +000033# This is organized as one test for each chunk of code in tempfile.py,
34# in order of their appearance in the file. Testing which requires
35# threads is not done here.
36
Gregory P. Smithad577b92015-05-22 16:18:14 -070037class TestLowLevelInternals(unittest.TestCase):
38 def test_infer_return_type_singles(self):
39 self.assertIs(str, tempfile._infer_return_type(''))
40 self.assertIs(bytes, tempfile._infer_return_type(b''))
41 self.assertIs(str, tempfile._infer_return_type(None))
42
43 def test_infer_return_type_multiples(self):
44 self.assertIs(str, tempfile._infer_return_type('', ''))
45 self.assertIs(bytes, tempfile._infer_return_type(b'', b''))
46 with self.assertRaises(TypeError):
47 tempfile._infer_return_type('', b'')
48 with self.assertRaises(TypeError):
49 tempfile._infer_return_type(b'', '')
50
51 def test_infer_return_type_multiples_and_none(self):
52 self.assertIs(str, tempfile._infer_return_type(None, ''))
53 self.assertIs(str, tempfile._infer_return_type('', None))
54 self.assertIs(str, tempfile._infer_return_type(None, None))
55 self.assertIs(bytes, tempfile._infer_return_type(b'', None))
56 self.assertIs(bytes, tempfile._infer_return_type(None, b''))
57 with self.assertRaises(TypeError):
58 tempfile._infer_return_type('', None, b'')
59 with self.assertRaises(TypeError):
60 tempfile._infer_return_type(b'', None, '')
61
Anthony Sottile370138b2019-09-09 08:54:34 -070062 def test_infer_return_type_pathlib(self):
63 self.assertIs(str, tempfile._infer_return_type(pathlib.Path('/')))
64
Miss Islington (bot)64e83c72021-10-20 14:27:30 -070065 def test_infer_return_type_pathlike(self):
66 class Path:
67 def __init__(self, path):
68 self.path = path
69
70 def __fspath__(self):
71 return self.path
72
73 self.assertIs(str, tempfile._infer_return_type(Path('/')))
74 self.assertIs(bytes, tempfile._infer_return_type(Path(b'/')))
75 self.assertIs(str, tempfile._infer_return_type('', Path('')))
76 self.assertIs(bytes, tempfile._infer_return_type(b'', Path(b'')))
77 self.assertIs(bytes, tempfile._infer_return_type(None, Path(b'')))
78 self.assertIs(str, tempfile._infer_return_type(None, Path('')))
79
80 with self.assertRaises(TypeError):
81 tempfile._infer_return_type('', Path(b''))
82 with self.assertRaises(TypeError):
83 tempfile._infer_return_type(b'', Path(''))
Gregory P. Smithad577b92015-05-22 16:18:14 -070084
Guido van Rossum0e548712002-08-09 16:14:33 +000085# Common functionality.
Gregory P. Smithad577b92015-05-22 16:18:14 -070086
Antoine Pitroueab2a502012-03-10 16:34:40 +010087class BaseTestCase(unittest.TestCase):
Guido van Rossum0e548712002-08-09 16:14:33 +000088
Victor Stinner97869102013-08-14 01:28:28 +020089 str_check = re.compile(r"^[a-z0-9_-]{8}$")
Gregory P. Smithad577b92015-05-22 16:18:14 -070090 b_check = re.compile(br"^[a-z0-9_-]{8}$")
Guido van Rossum0e548712002-08-09 16:14:33 +000091
Brett Cannone1adece2010-03-20 22:19:55 +000092 def setUp(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +080093 self._warnings_manager = warnings_helper.check_warnings()
Brett Cannone1adece2010-03-20 22:19:55 +000094 self._warnings_manager.__enter__()
95 warnings.filterwarnings("ignore", category=RuntimeWarning,
96 message="mktemp", module=__name__)
97
98 def tearDown(self):
99 self._warnings_manager.__exit__(None, None, None)
100
Guido van Rossum0e548712002-08-09 16:14:33 +0000101 def nameCheck(self, name, dir, pre, suf):
102 (ndir, nbase) = os.path.split(name)
103 npre = nbase[:len(pre)]
104 nsuf = nbase[len(nbase)-len(suf):]
105
Gregory P. Smithad577b92015-05-22 16:18:14 -0700106 if dir is not None:
Anthony Sottile370138b2019-09-09 08:54:34 -0700107 self.assertIs(
108 type(name),
109 str
110 if type(dir) is str or isinstance(dir, os.PathLike) else
111 bytes,
112 "unexpected return type",
113 )
Gregory P. Smithad577b92015-05-22 16:18:14 -0700114 if pre is not None:
115 self.assertIs(type(name), str if type(pre) is str else bytes,
116 "unexpected return type")
117 if suf is not None:
118 self.assertIs(type(name), str if type(suf) is str else bytes,
119 "unexpected return type")
120 if (dir, pre, suf) == (None, None, None):
121 self.assertIs(type(name), str, "default return type must be str")
122
Martin v. Löwisd6625482003-10-12 17:37:01 +0000123 # check for equality of the absolute paths!
124 self.assertEqual(os.path.abspath(ndir), os.path.abspath(dir),
Gregory P. Smithad577b92015-05-22 16:18:14 -0700125 "file %r not in directory %r" % (name, dir))
Guido van Rossum0e548712002-08-09 16:14:33 +0000126 self.assertEqual(npre, pre,
Gregory P. Smithad577b92015-05-22 16:18:14 -0700127 "file %r does not begin with %r" % (nbase, pre))
Guido van Rossum0e548712002-08-09 16:14:33 +0000128 self.assertEqual(nsuf, suf,
Gregory P. Smithad577b92015-05-22 16:18:14 -0700129 "file %r does not end with %r" % (nbase, suf))
Guido van Rossum0e548712002-08-09 16:14:33 +0000130
131 nbase = nbase[len(pre):len(nbase)-len(suf)]
Gregory P. Smithad577b92015-05-22 16:18:14 -0700132 check = self.str_check if isinstance(nbase, str) else self.b_check
133 self.assertTrue(check.match(nbase),
134 "random characters %r do not match %r"
135 % (nbase, check.pattern))
Guido van Rossum0e548712002-08-09 16:14:33 +0000136
Guido van Rossum0e548712002-08-09 16:14:33 +0000137
Antoine Pitroueab2a502012-03-10 16:34:40 +0100138class TestExports(BaseTestCase):
Guido van Rossum0e548712002-08-09 16:14:33 +0000139 def test_exports(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000140 # There are no surprising symbols in the tempfile module
Guido van Rossum0e548712002-08-09 16:14:33 +0000141 dict = tempfile.__dict__
142
143 expected = {
144 "NamedTemporaryFile" : 1,
145 "TemporaryFile" : 1,
146 "mkstemp" : 1,
147 "mkdtemp" : 1,
148 "mktemp" : 1,
149 "TMP_MAX" : 1,
150 "gettempprefix" : 1,
Gregory P. Smithad577b92015-05-22 16:18:14 -0700151 "gettempprefixb" : 1,
Guido van Rossum0e548712002-08-09 16:14:33 +0000152 "gettempdir" : 1,
Gregory P. Smithad577b92015-05-22 16:18:14 -0700153 "gettempdirb" : 1,
Guido van Rossum0e548712002-08-09 16:14:33 +0000154 "tempdir" : 1,
Guido van Rossumd8faa362007-04-27 19:54:29 +0000155 "template" : 1,
Nick Coghlan543af752010-10-24 11:23:25 +0000156 "SpooledTemporaryFile" : 1,
157 "TemporaryDirectory" : 1,
Guido van Rossum0e548712002-08-09 16:14:33 +0000158 }
159
160 unexp = []
161 for key in dict:
162 if key[0] != '_' and key not in expected:
163 unexp.append(key)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000164 self.assertTrue(len(unexp) == 0,
Guido van Rossum0e548712002-08-09 16:14:33 +0000165 "unexpected keys: %s" % unexp)
166
Guido van Rossum0e548712002-08-09 16:14:33 +0000167
Antoine Pitroueab2a502012-03-10 16:34:40 +0100168class TestRandomNameSequence(BaseTestCase):
Guido van Rossum0e548712002-08-09 16:14:33 +0000169 """Test the internal iterator object _RandomNameSequence."""
170
171 def setUp(self):
172 self.r = tempfile._RandomNameSequence()
Brett Cannone1adece2010-03-20 22:19:55 +0000173 super().setUp()
Guido van Rossum0e548712002-08-09 16:14:33 +0000174
Inada Naokid2810052020-11-01 20:02:03 +0900175 def test_get_eight_char_str(self):
176 # _RandomNameSequence returns a eight-character string
Georg Brandla18af4e2007-04-21 15:47:16 +0000177 s = next(self.r)
Guido van Rossum0e548712002-08-09 16:14:33 +0000178 self.nameCheck(s, '', '', '')
179
180 def test_many(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000181 # _RandomNameSequence returns no duplicate strings (stochastic)
Guido van Rossum0e548712002-08-09 16:14:33 +0000182
183 dict = {}
184 r = self.r
Guido van Rossum805365e2007-05-07 22:24:25 +0000185 for i in range(TEST_FILES):
Georg Brandla18af4e2007-04-21 15:47:16 +0000186 s = next(r)
Guido van Rossum0e548712002-08-09 16:14:33 +0000187 self.nameCheck(s, '', '', '')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000188 self.assertNotIn(s, dict)
Guido van Rossum0e548712002-08-09 16:14:33 +0000189 dict[s] = 1
190
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000191 def supports_iter(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000192 # _RandomNameSequence supports the iterator protocol
Guido van Rossum0e548712002-08-09 16:14:33 +0000193
194 i = 0
195 r = self.r
Antoine Pitrou8cd8d5e2012-03-10 16:20:24 +0100196 for s in r:
197 i += 1
198 if i == 20:
199 break
Guido van Rossum0e548712002-08-09 16:14:33 +0000200
Antoine Pitrou4558bad2011-11-25 21:28:15 +0100201 @unittest.skipUnless(hasattr(os, 'fork'),
202 "os.fork is required for this test")
203 def test_process_awareness(self):
204 # ensure that the random source differs between
205 # child and parent.
206 read_fd, write_fd = os.pipe()
207 pid = None
208 try:
209 pid = os.fork()
210 if not pid:
Victor Stinner6c8c2942017-08-10 13:05:06 +0200211 # child process
Antoine Pitrou4558bad2011-11-25 21:28:15 +0100212 os.close(read_fd)
213 os.write(write_fd, next(self.r).encode("ascii"))
214 os.close(write_fd)
215 # bypass the normal exit handlers- leave those to
216 # the parent.
217 os._exit(0)
Victor Stinner6c8c2942017-08-10 13:05:06 +0200218
219 # parent process
Antoine Pitrou4558bad2011-11-25 21:28:15 +0100220 parent_value = next(self.r)
221 child_value = os.read(read_fd, len(parent_value)).decode("ascii")
222 finally:
223 if pid:
Victor Stinner278c1e12020-03-31 20:08:12 +0200224 support.wait_process(pid, exitcode=0)
Victor Stinner6c8c2942017-08-10 13:05:06 +0200225
Antoine Pitrou4558bad2011-11-25 21:28:15 +0100226 os.close(read_fd)
227 os.close(write_fd)
228 self.assertNotEqual(child_value, parent_value)
229
230
Guido van Rossum0e548712002-08-09 16:14:33 +0000231
Antoine Pitroueab2a502012-03-10 16:34:40 +0100232class TestCandidateTempdirList(BaseTestCase):
Guido van Rossum0e548712002-08-09 16:14:33 +0000233 """Test the internal function _candidate_tempdir_list."""
234
235 def test_nonempty_list(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000236 # _candidate_tempdir_list returns a nonempty list of strings
Guido van Rossum0e548712002-08-09 16:14:33 +0000237
238 cand = tempfile._candidate_tempdir_list()
239
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000240 self.assertFalse(len(cand) == 0)
Guido van Rossum0e548712002-08-09 16:14:33 +0000241 for c in cand:
Ezio Melottie9615932010-01-24 19:26:24 +0000242 self.assertIsInstance(c, str)
Guido van Rossum0e548712002-08-09 16:14:33 +0000243
244 def test_wanted_dirs(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000245 # _candidate_tempdir_list contains the expected directories
Guido van Rossum0e548712002-08-09 16:14:33 +0000246
247 # Make sure the interesting environment variables are all set.
Hai Shi0c4f0f32020-06-30 21:46:31 +0800248 with os_helper.EnvironmentVarGuard() as env:
Guido van Rossum0e548712002-08-09 16:14:33 +0000249 for envname in 'TMPDIR', 'TEMP', 'TMP':
250 dirname = os.getenv(envname)
251 if not dirname:
Walter Dörwald155374d2009-05-01 19:58:58 +0000252 env[envname] = os.path.abspath(envname)
Guido van Rossum0e548712002-08-09 16:14:33 +0000253
254 cand = tempfile._candidate_tempdir_list()
255
256 for envname in 'TMPDIR', 'TEMP', 'TMP':
257 dirname = os.getenv(envname)
258 if not dirname: raise ValueError
Benjamin Peterson577473f2010-01-19 00:09:57 +0000259 self.assertIn(dirname, cand)
Guido van Rossum0e548712002-08-09 16:14:33 +0000260
261 try:
262 dirname = os.getcwd()
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200263 except (AttributeError, OSError):
Guido van Rossum0e548712002-08-09 16:14:33 +0000264 dirname = os.curdir
265
Benjamin Peterson577473f2010-01-19 00:09:57 +0000266 self.assertIn(dirname, cand)
Guido van Rossum0e548712002-08-09 16:14:33 +0000267
268 # Not practical to try to verify the presence of OS-specific
269 # paths in this list.
Guido van Rossum0e548712002-08-09 16:14:33 +0000270
Guido van Rossum0e548712002-08-09 16:14:33 +0000271
Serhiy Storchakaf6b361e2013-02-13 00:35:30 +0200272# We test _get_default_tempdir some more by testing gettempdir.
Guido van Rossum0e548712002-08-09 16:14:33 +0000273
Serhiy Storchakaff7fef92013-02-13 00:37:29 +0200274class TestGetDefaultTempdir(BaseTestCase):
Serhiy Storchakaf6b361e2013-02-13 00:35:30 +0200275 """Test _get_default_tempdir()."""
276
277 def test_no_files_left_behind(self):
278 # use a private empty directory
279 with tempfile.TemporaryDirectory() as our_temp_directory:
280 # force _get_default_tempdir() to consider our empty directory
281 def our_candidate_list():
282 return [our_temp_directory]
283
284 with support.swap_attr(tempfile, "_candidate_tempdir_list",
285 our_candidate_list):
286 # verify our directory is empty after _get_default_tempdir()
287 tempfile._get_default_tempdir()
288 self.assertEqual(os.listdir(our_temp_directory), [])
289
290 def raise_OSError(*args, **kwargs):
Serhiy Storchakaff7fef92013-02-13 00:37:29 +0200291 raise OSError()
Serhiy Storchakaf6b361e2013-02-13 00:35:30 +0200292
293 with support.swap_attr(io, "open", raise_OSError):
294 # test again with failing io.open()
Serhiy Storchakaff7fef92013-02-13 00:37:29 +0200295 with self.assertRaises(FileNotFoundError):
Serhiy Storchakaf6b361e2013-02-13 00:35:30 +0200296 tempfile._get_default_tempdir()
Serhiy Storchakaf6b361e2013-02-13 00:35:30 +0200297 self.assertEqual(os.listdir(our_temp_directory), [])
298
Serhiy Storchakaf6b361e2013-02-13 00:35:30 +0200299 def bad_writer(*args, **kwargs):
Serhiy Storchakad1a1def2017-04-28 19:17:26 +0300300 fp = orig_open(*args, **kwargs)
Serhiy Storchakaf6b361e2013-02-13 00:35:30 +0200301 fp.write = raise_OSError
302 return fp
303
Serhiy Storchakad1a1def2017-04-28 19:17:26 +0300304 with support.swap_attr(io, "open", bad_writer) as orig_open:
Serhiy Storchakaf6b361e2013-02-13 00:35:30 +0200305 # test again with failing write()
Serhiy Storchakaff7fef92013-02-13 00:37:29 +0200306 with self.assertRaises(FileNotFoundError):
Serhiy Storchakaf6b361e2013-02-13 00:35:30 +0200307 tempfile._get_default_tempdir()
Serhiy Storchakaf6b361e2013-02-13 00:35:30 +0200308 self.assertEqual(os.listdir(our_temp_directory), [])
Guido van Rossum0e548712002-08-09 16:14:33 +0000309
310
Antoine Pitroueab2a502012-03-10 16:34:40 +0100311class TestGetCandidateNames(BaseTestCase):
Guido van Rossum0e548712002-08-09 16:14:33 +0000312 """Test the internal function _get_candidate_names."""
313
314 def test_retval(self):
Victor Stinner1e62bf12017-04-19 22:59:51 +0200315 # _get_candidate_names returns a _RandomNameSequence object
Guido van Rossum0e548712002-08-09 16:14:33 +0000316 obj = tempfile._get_candidate_names()
Victor Stinner1e62bf12017-04-19 22:59:51 +0200317 self.assertIsInstance(obj, tempfile._RandomNameSequence)
Guido van Rossum0e548712002-08-09 16:14:33 +0000318
319 def test_same_thing(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000320 # _get_candidate_names always returns the same object
Guido van Rossum0e548712002-08-09 16:14:33 +0000321 a = tempfile._get_candidate_names()
322 b = tempfile._get_candidate_names()
323
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000324 self.assertTrue(a is b)
Guido van Rossum0e548712002-08-09 16:14:33 +0000325
Guido van Rossum0e548712002-08-09 16:14:33 +0000326
Eli Benderskyaa04f9a2013-09-13 05:28:20 -0700327@contextlib.contextmanager
328def _inside_empty_temp_dir():
329 dir = tempfile.mkdtemp()
330 try:
331 with support.swap_attr(tempfile, 'tempdir', dir):
332 yield
333 finally:
Hai Shi0c4f0f32020-06-30 21:46:31 +0800334 os_helper.rmtree(dir)
Eli Benderskyaa04f9a2013-09-13 05:28:20 -0700335
336
337def _mock_candidate_names(*names):
338 return support.swap_attr(tempfile,
339 '_get_candidate_names',
340 lambda: iter(names))
341
342
Serhiy Storchaka5d6b7b12015-05-20 00:11:48 +0300343class TestBadTempdir:
344
345 def test_read_only_directory(self):
346 with _inside_empty_temp_dir():
347 oldmode = mode = os.stat(tempfile.tempdir).st_mode
348 mode &= ~(stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH)
349 os.chmod(tempfile.tempdir, mode)
350 try:
351 if os.access(tempfile.tempdir, os.W_OK):
352 self.skipTest("can't set the directory read-only")
353 with self.assertRaises(PermissionError):
354 self.make_temp()
355 self.assertEqual(os.listdir(tempfile.tempdir), [])
356 finally:
357 os.chmod(tempfile.tempdir, oldmode)
358
359 def test_nonexisting_directory(self):
360 with _inside_empty_temp_dir():
361 tempdir = os.path.join(tempfile.tempdir, 'nonexistent')
362 with support.swap_attr(tempfile, 'tempdir', tempdir):
363 with self.assertRaises(FileNotFoundError):
364 self.make_temp()
365
366 def test_non_directory(self):
367 with _inside_empty_temp_dir():
368 tempdir = os.path.join(tempfile.tempdir, 'file')
369 open(tempdir, 'wb').close()
370 with support.swap_attr(tempfile, 'tempdir', tempdir):
371 with self.assertRaises((NotADirectoryError, FileNotFoundError)):
372 self.make_temp()
373
374
375class TestMkstempInner(TestBadTempdir, BaseTestCase):
Guido van Rossum0e548712002-08-09 16:14:33 +0000376 """Test the internal function _mkstemp_inner."""
377
378 class mkstemped:
379 _bflags = tempfile._bin_openflags
380 _tflags = tempfile._text_openflags
381 _close = os.close
382 _unlink = os.unlink
383
384 def __init__(self, dir, pre, suf, bin):
385 if bin: flags = self._bflags
386 else: flags = self._tflags
387
Gregory P. Smithad577b92015-05-22 16:18:14 -0700388 output_type = tempfile._infer_return_type(dir, pre, suf)
389 (self.fd, self.name) = tempfile._mkstemp_inner(dir, pre, suf, flags, output_type)
Guido van Rossum0e548712002-08-09 16:14:33 +0000390
391 def write(self, str):
392 os.write(self.fd, str)
393
394 def __del__(self):
395 self._close(self.fd)
396 self._unlink(self.name)
Tim Petersa0d55de2002-08-09 18:01:01 +0000397
Gregory P. Smithad577b92015-05-22 16:18:14 -0700398 def do_create(self, dir=None, pre=None, suf=None, bin=1):
399 output_type = tempfile._infer_return_type(dir, pre, suf)
Guido van Rossum0e548712002-08-09 16:14:33 +0000400 if dir is None:
Gregory P. Smithad577b92015-05-22 16:18:14 -0700401 if output_type is str:
402 dir = tempfile.gettempdir()
403 else:
404 dir = tempfile.gettempdirb()
405 if pre is None:
406 pre = output_type()
407 if suf is None:
408 suf = output_type()
Antoine Pitrou8cd8d5e2012-03-10 16:20:24 +0100409 file = self.mkstemped(dir, pre, suf, bin)
Guido van Rossum0e548712002-08-09 16:14:33 +0000410
411 self.nameCheck(file.name, dir, pre, suf)
412 return file
413
414 def test_basic(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000415 # _mkstemp_inner can create files
Guido van Rossumec42ffd2007-08-27 23:40:36 +0000416 self.do_create().write(b"blat")
417 self.do_create(pre="a").write(b"blat")
418 self.do_create(suf="b").write(b"blat")
419 self.do_create(pre="a", suf="b").write(b"blat")
420 self.do_create(pre="aa", suf=".txt").write(b"blat")
Guido van Rossum0e548712002-08-09 16:14:33 +0000421
Gregory P. Smithad577b92015-05-22 16:18:14 -0700422 def test_basic_with_bytes_names(self):
423 # _mkstemp_inner can create files when given name parts all
424 # specified as bytes.
425 dir_b = tempfile.gettempdirb()
426 self.do_create(dir=dir_b, suf=b"").write(b"blat")
427 self.do_create(dir=dir_b, pre=b"a").write(b"blat")
428 self.do_create(dir=dir_b, suf=b"b").write(b"blat")
429 self.do_create(dir=dir_b, pre=b"a", suf=b"b").write(b"blat")
430 self.do_create(dir=dir_b, pre=b"aa", suf=b".txt").write(b"blat")
431 # Can't mix str & binary types in the args.
432 with self.assertRaises(TypeError):
433 self.do_create(dir="", suf=b"").write(b"blat")
434 with self.assertRaises(TypeError):
435 self.do_create(dir=dir_b, pre="").write(b"blat")
436 with self.assertRaises(TypeError):
437 self.do_create(dir=dir_b, pre=b"", suf="").write(b"blat")
438
Guido van Rossum0e548712002-08-09 16:14:33 +0000439 def test_basic_many(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000440 # _mkstemp_inner can create many files (stochastic)
Guido van Rossum805365e2007-05-07 22:24:25 +0000441 extant = list(range(TEST_FILES))
Guido van Rossum0e548712002-08-09 16:14:33 +0000442 for i in extant:
443 extant[i] = self.do_create(pre="aa")
444
445 def test_choose_directory(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000446 # _mkstemp_inner can create files in a user-selected directory
Guido van Rossum0e548712002-08-09 16:14:33 +0000447 dir = tempfile.mkdtemp()
448 try:
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +0000449 self.do_create(dir=dir).write(b"blat")
Anthony Sottile370138b2019-09-09 08:54:34 -0700450 self.do_create(dir=pathlib.Path(dir)).write(b"blat")
Guido van Rossum0e548712002-08-09 16:14:33 +0000451 finally:
Serhiy Storchaka462c1f02021-09-08 18:08:57 +0300452 support.gc_collect() # For PyPy or other GCs.
Guido van Rossum0e548712002-08-09 16:14:33 +0000453 os.rmdir(dir)
454
455 def test_file_mode(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000456 # _mkstemp_inner creates files with the proper mode
Guido van Rossum0e548712002-08-09 16:14:33 +0000457
458 file = self.do_create()
459 mode = stat.S_IMODE(os.stat(file.name).st_mode)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000460 expected = 0o600
Jesus Cea4791a242012-10-05 03:15:39 +0200461 if sys.platform == 'win32':
Tim Petersca3ac7f2002-08-09 18:13:51 +0000462 # There's no distinction among 'user', 'group' and 'world';
463 # replicate the 'user' bits.
464 user = expected >> 6
465 expected = user * (1 + 8 + 64)
466 self.assertEqual(mode, expected)
Guido van Rossum0e548712002-08-09 16:14:33 +0000467
Zachary Ware9fe6d862013-12-08 00:20:35 -0600468 @unittest.skipUnless(has_spawnl, 'os.spawnl not available')
Guido van Rossum0e548712002-08-09 16:14:33 +0000469 def test_noinherit(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000470 # _mkstemp_inner file handles are not inherited by child processes
Guido van Rossum0e548712002-08-09 16:14:33 +0000471
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000472 if support.verbose:
Guido van Rossum78741062002-08-17 11:41:01 +0000473 v="v"
474 else:
475 v="q"
476
Guido van Rossum0e548712002-08-09 16:14:33 +0000477 file = self.do_create()
Victor Stinnerdaf45552013-08-28 00:53:59 +0200478 self.assertEqual(os.get_inheritable(file.fd), False)
Guido van Rossum78741062002-08-17 11:41:01 +0000479 fd = "%d" % file.fd
480
481 try:
482 me = __file__
483 except NameError:
484 me = sys.argv[0]
Guido van Rossum0e548712002-08-09 16:14:33 +0000485
486 # We have to exec something, so that FD_CLOEXEC will take
Guido van Rossum78741062002-08-17 11:41:01 +0000487 # effect. The core of this test is therefore in
488 # tf_inherit_check.py, which see.
489 tester = os.path.join(os.path.dirname(os.path.abspath(me)),
490 "tf_inherit_check.py")
Guido van Rossum0e548712002-08-09 16:14:33 +0000491
Martin v. Löwisd4210bc2003-10-23 15:55:28 +0000492 # On Windows a spawn* /path/ with embedded spaces shouldn't be quoted,
493 # but an arg with embedded spaces should be decorated with double
494 # quotes on each end
Jesus Cea4791a242012-10-05 03:15:39 +0200495 if sys.platform == 'win32':
Martin v. Löwisd4210bc2003-10-23 15:55:28 +0000496 decorated = '"%s"' % sys.executable
497 tester = '"%s"' % tester
498 else:
499 decorated = sys.executable
500
501 retval = os.spawnl(os.P_WAIT, sys.executable, decorated, tester, v, fd)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000502 self.assertFalse(retval < 0,
Guido van Rossum78741062002-08-17 11:41:01 +0000503 "child process caught fatal signal %d" % -retval)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000504 self.assertFalse(retval > 0, "child process reports failure %d"%retval)
Guido van Rossum0e548712002-08-09 16:14:33 +0000505
Zachary Ware9fe6d862013-12-08 00:20:35 -0600506 @unittest.skipUnless(has_textmode, "text mode not available")
Guido van Rossum0e548712002-08-09 16:14:33 +0000507 def test_textmode(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000508 # _mkstemp_inner can create files in text mode
Guido van Rossum0e548712002-08-09 16:14:33 +0000509
Amaury Forgeot d'Arc7d0bddd2009-11-30 00:08:56 +0000510 # A text file is truncated at the first Ctrl+Z byte
511 f = self.do_create(bin=0)
512 f.write(b"blat\x1a")
513 f.write(b"extra\n")
514 os.lseek(f.fd, 0, os.SEEK_SET)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000515 self.assertEqual(os.read(f.fd, 20), b"blat")
Guido van Rossum0e548712002-08-09 16:14:33 +0000516
Serhiy Storchaka5d6b7b12015-05-20 00:11:48 +0300517 def make_temp(self):
Eli Benderskyaa04f9a2013-09-13 05:28:20 -0700518 return tempfile._mkstemp_inner(tempfile.gettempdir(),
Gregory P. Smithad577b92015-05-22 16:18:14 -0700519 tempfile.gettempprefix(),
Eli Benderskyaa04f9a2013-09-13 05:28:20 -0700520 '',
Gregory P. Smithad577b92015-05-22 16:18:14 -0700521 tempfile._bin_openflags,
522 str)
Eli Benderskyaa04f9a2013-09-13 05:28:20 -0700523
524 def test_collision_with_existing_file(self):
525 # _mkstemp_inner tries another name when a file with
526 # the chosen name already exists
527 with _inside_empty_temp_dir(), \
528 _mock_candidate_names('aaa', 'aaa', 'bbb'):
Serhiy Storchaka5d6b7b12015-05-20 00:11:48 +0300529 (fd1, name1) = self.make_temp()
Eli Benderskyaa04f9a2013-09-13 05:28:20 -0700530 os.close(fd1)
531 self.assertTrue(name1.endswith('aaa'))
532
Serhiy Storchaka5d6b7b12015-05-20 00:11:48 +0300533 (fd2, name2) = self.make_temp()
Eli Benderskyaa04f9a2013-09-13 05:28:20 -0700534 os.close(fd2)
535 self.assertTrue(name2.endswith('bbb'))
536
Eli Benderskyf315df32013-09-06 06:11:19 -0700537 def test_collision_with_existing_directory(self):
538 # _mkstemp_inner tries another name when a directory with
539 # the chosen name already exists
Eli Benderskyaa04f9a2013-09-13 05:28:20 -0700540 with _inside_empty_temp_dir(), \
541 _mock_candidate_names('aaa', 'aaa', 'bbb'):
542 dir = tempfile.mkdtemp()
543 self.assertTrue(dir.endswith('aaa'))
Eli Benderskyf315df32013-09-06 06:11:19 -0700544
Serhiy Storchaka5d6b7b12015-05-20 00:11:48 +0300545 (fd, name) = self.make_temp()
Eli Benderskyaa04f9a2013-09-13 05:28:20 -0700546 os.close(fd)
547 self.assertTrue(name.endswith('bbb'))
Eli Benderskyf315df32013-09-06 06:11:19 -0700548
Guido van Rossum0e548712002-08-09 16:14:33 +0000549
Antoine Pitroueab2a502012-03-10 16:34:40 +0100550class TestGetTempPrefix(BaseTestCase):
Guido van Rossum0e548712002-08-09 16:14:33 +0000551 """Test gettempprefix()."""
552
553 def test_sane_template(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000554 # gettempprefix returns a nonempty prefix string
Guido van Rossum0e548712002-08-09 16:14:33 +0000555 p = tempfile.gettempprefix()
556
Ezio Melottie9615932010-01-24 19:26:24 +0000557 self.assertIsInstance(p, str)
Gregory P. Smithad577b92015-05-22 16:18:14 -0700558 self.assertGreater(len(p), 0)
559
560 pb = tempfile.gettempprefixb()
561
562 self.assertIsInstance(pb, bytes)
563 self.assertGreater(len(pb), 0)
Guido van Rossum0e548712002-08-09 16:14:33 +0000564
565 def test_usable_template(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000566 # gettempprefix returns a usable prefix string
Guido van Rossum0e548712002-08-09 16:14:33 +0000567
568 # Create a temp directory, avoiding use of the prefix.
569 # Then attempt to create a file whose name is
570 # prefix + 'xxxxxx.xxx' in that directory.
571 p = tempfile.gettempprefix() + "xxxxxx.xxx"
572 d = tempfile.mkdtemp(prefix="")
573 try:
574 p = os.path.join(d, p)
Antoine Pitrou8cd8d5e2012-03-10 16:20:24 +0100575 fd = os.open(p, os.O_RDWR | os.O_CREAT)
Guido van Rossum0e548712002-08-09 16:14:33 +0000576 os.close(fd)
577 os.unlink(p)
578 finally:
579 os.rmdir(d)
580
Guido van Rossum0e548712002-08-09 16:14:33 +0000581
Antoine Pitroueab2a502012-03-10 16:34:40 +0100582class TestGetTempDir(BaseTestCase):
Guido van Rossum0e548712002-08-09 16:14:33 +0000583 """Test gettempdir()."""
584
585 def test_directory_exists(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000586 # gettempdir returns a directory which exists
Guido van Rossum0e548712002-08-09 16:14:33 +0000587
Gregory P. Smithad577b92015-05-22 16:18:14 -0700588 for d in (tempfile.gettempdir(), tempfile.gettempdirb()):
589 self.assertTrue(os.path.isabs(d) or d == os.curdir,
590 "%r is not an absolute path" % d)
591 self.assertTrue(os.path.isdir(d),
592 "%r is not a directory" % d)
Guido van Rossum0e548712002-08-09 16:14:33 +0000593
594 def test_directory_writable(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000595 # gettempdir returns a directory writable by the user
Guido van Rossum0e548712002-08-09 16:14:33 +0000596
597 # sneaky: just instantiate a NamedTemporaryFile, which
598 # defaults to writing into the directory returned by
599 # gettempdir.
Serhiy Storchaka5b10b982019-03-05 10:06:26 +0200600 with tempfile.NamedTemporaryFile() as file:
601 file.write(b"blat")
Guido van Rossum0e548712002-08-09 16:14:33 +0000602
603 def test_same_thing(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000604 # gettempdir always returns the same object
Guido van Rossum0e548712002-08-09 16:14:33 +0000605 a = tempfile.gettempdir()
606 b = tempfile.gettempdir()
Gregory P. Smithad577b92015-05-22 16:18:14 -0700607 c = tempfile.gettempdirb()
Guido van Rossum0e548712002-08-09 16:14:33 +0000608
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000609 self.assertTrue(a is b)
Gregory P. Smithad577b92015-05-22 16:18:14 -0700610 self.assertNotEqual(type(a), type(c))
611 self.assertEqual(a, os.fsdecode(c))
Guido van Rossum0e548712002-08-09 16:14:33 +0000612
Tim Golden6d09f092013-10-25 18:38:16 +0100613 def test_case_sensitive(self):
614 # gettempdir should not flatten its case
615 # even on a case-insensitive file system
616 case_sensitive_tempdir = tempfile.mkdtemp("-Temp")
617 _tempdir, tempfile.tempdir = tempfile.tempdir, None
618 try:
Hai Shi0c4f0f32020-06-30 21:46:31 +0800619 with os_helper.EnvironmentVarGuard() as env:
Tim Golden6d09f092013-10-25 18:38:16 +0100620 # Fake the first env var which is checked as a candidate
621 env["TMPDIR"] = case_sensitive_tempdir
622 self.assertEqual(tempfile.gettempdir(), case_sensitive_tempdir)
623 finally:
624 tempfile.tempdir = _tempdir
Hai Shi0c4f0f32020-06-30 21:46:31 +0800625 os_helper.rmdir(case_sensitive_tempdir)
Tim Golden6d09f092013-10-25 18:38:16 +0100626
Guido van Rossum0e548712002-08-09 16:14:33 +0000627
Antoine Pitroueab2a502012-03-10 16:34:40 +0100628class TestMkstemp(BaseTestCase):
Guido van Rossum0e548712002-08-09 16:14:33 +0000629 """Test mkstemp()."""
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000630
Gregory P. Smithad577b92015-05-22 16:18:14 -0700631 def do_create(self, dir=None, pre=None, suf=None):
632 output_type = tempfile._infer_return_type(dir, pre, suf)
Guido van Rossum0e548712002-08-09 16:14:33 +0000633 if dir is None:
Gregory P. Smithad577b92015-05-22 16:18:14 -0700634 if output_type is str:
635 dir = tempfile.gettempdir()
636 else:
637 dir = tempfile.gettempdirb()
638 if pre is None:
639 pre = output_type()
640 if suf is None:
641 suf = output_type()
Antoine Pitrou8cd8d5e2012-03-10 16:20:24 +0100642 (fd, name) = tempfile.mkstemp(dir=dir, prefix=pre, suffix=suf)
643 (ndir, nbase) = os.path.split(name)
644 adir = os.path.abspath(dir)
645 self.assertEqual(adir, ndir,
646 "Directory '%s' incorrectly returned as '%s'" % (adir, ndir))
Guido van Rossum0e548712002-08-09 16:14:33 +0000647
648 try:
649 self.nameCheck(name, dir, pre, suf)
650 finally:
651 os.close(fd)
652 os.unlink(name)
653
654 def test_basic(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000655 # mkstemp can create files
Guido van Rossum0e548712002-08-09 16:14:33 +0000656 self.do_create()
657 self.do_create(pre="a")
658 self.do_create(suf="b")
659 self.do_create(pre="a", suf="b")
660 self.do_create(pre="aa", suf=".txt")
Martin v. Löwisd6625482003-10-12 17:37:01 +0000661 self.do_create(dir=".")
Guido van Rossum0e548712002-08-09 16:14:33 +0000662
Gregory P. Smithad577b92015-05-22 16:18:14 -0700663 def test_basic_with_bytes_names(self):
664 # mkstemp can create files when given name parts all
665 # specified as bytes.
666 d = tempfile.gettempdirb()
667 self.do_create(dir=d, suf=b"")
668 self.do_create(dir=d, pre=b"a")
669 self.do_create(dir=d, suf=b"b")
670 self.do_create(dir=d, pre=b"a", suf=b"b")
671 self.do_create(dir=d, pre=b"aa", suf=b".txt")
672 self.do_create(dir=b".")
673 with self.assertRaises(TypeError):
674 self.do_create(dir=".", pre=b"aa", suf=b".txt")
675 with self.assertRaises(TypeError):
676 self.do_create(dir=b".", pre="aa", suf=b".txt")
677 with self.assertRaises(TypeError):
678 self.do_create(dir=b".", pre=b"aa", suf=".txt")
679
680
Guido van Rossum0e548712002-08-09 16:14:33 +0000681 def test_choose_directory(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000682 # mkstemp can create directories in a user-selected directory
Guido van Rossum0e548712002-08-09 16:14:33 +0000683 dir = tempfile.mkdtemp()
684 try:
685 self.do_create(dir=dir)
Anthony Sottile370138b2019-09-09 08:54:34 -0700686 self.do_create(dir=pathlib.Path(dir))
Guido van Rossum0e548712002-08-09 16:14:33 +0000687 finally:
688 os.rmdir(dir)
689
Eric L9c792742021-03-03 21:36:22 +0100690 def test_for_tempdir_is_bytes_issue40701_api_warts(self):
691 orig_tempdir = tempfile.tempdir
692 self.assertIsInstance(tempfile.tempdir, (str, type(None)))
693 try:
694 fd, path = tempfile.mkstemp()
695 os.close(fd)
696 os.unlink(path)
697 self.assertIsInstance(path, str)
698 tempfile.tempdir = tempfile.gettempdirb()
699 self.assertIsInstance(tempfile.tempdir, bytes)
700 self.assertIsInstance(tempfile.gettempdir(), str)
701 self.assertIsInstance(tempfile.gettempdirb(), bytes)
702 fd, path = tempfile.mkstemp()
703 os.close(fd)
704 os.unlink(path)
705 self.assertIsInstance(path, bytes)
706 fd, path = tempfile.mkstemp(suffix='.txt')
707 os.close(fd)
708 os.unlink(path)
709 self.assertIsInstance(path, str)
710 fd, path = tempfile.mkstemp(prefix='test-temp-')
711 os.close(fd)
712 os.unlink(path)
713 self.assertIsInstance(path, str)
714 fd, path = tempfile.mkstemp(dir=tempfile.gettempdir())
715 os.close(fd)
716 os.unlink(path)
717 self.assertIsInstance(path, str)
718 finally:
719 tempfile.tempdir = orig_tempdir
720
Guido van Rossum0e548712002-08-09 16:14:33 +0000721
Serhiy Storchaka5d6b7b12015-05-20 00:11:48 +0300722class TestMkdtemp(TestBadTempdir, BaseTestCase):
Guido van Rossum0e548712002-08-09 16:14:33 +0000723 """Test mkdtemp()."""
724
Serhiy Storchaka5d6b7b12015-05-20 00:11:48 +0300725 def make_temp(self):
726 return tempfile.mkdtemp()
727
Gregory P. Smithad577b92015-05-22 16:18:14 -0700728 def do_create(self, dir=None, pre=None, suf=None):
729 output_type = tempfile._infer_return_type(dir, pre, suf)
Guido van Rossum0e548712002-08-09 16:14:33 +0000730 if dir is None:
Gregory P. Smithad577b92015-05-22 16:18:14 -0700731 if output_type is str:
732 dir = tempfile.gettempdir()
733 else:
734 dir = tempfile.gettempdirb()
735 if pre is None:
736 pre = output_type()
737 if suf is None:
738 suf = output_type()
Antoine Pitrou8cd8d5e2012-03-10 16:20:24 +0100739 name = tempfile.mkdtemp(dir=dir, prefix=pre, suffix=suf)
Guido van Rossum0e548712002-08-09 16:14:33 +0000740
741 try:
742 self.nameCheck(name, dir, pre, suf)
743 return name
744 except:
745 os.rmdir(name)
746 raise
747
748 def test_basic(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000749 # mkdtemp can create directories
Guido van Rossum0e548712002-08-09 16:14:33 +0000750 os.rmdir(self.do_create())
751 os.rmdir(self.do_create(pre="a"))
752 os.rmdir(self.do_create(suf="b"))
753 os.rmdir(self.do_create(pre="a", suf="b"))
754 os.rmdir(self.do_create(pre="aa", suf=".txt"))
Tim Petersa0d55de2002-08-09 18:01:01 +0000755
Gregory P. Smithad577b92015-05-22 16:18:14 -0700756 def test_basic_with_bytes_names(self):
757 # mkdtemp can create directories when given all binary parts
758 d = tempfile.gettempdirb()
759 os.rmdir(self.do_create(dir=d))
760 os.rmdir(self.do_create(dir=d, pre=b"a"))
761 os.rmdir(self.do_create(dir=d, suf=b"b"))
762 os.rmdir(self.do_create(dir=d, pre=b"a", suf=b"b"))
763 os.rmdir(self.do_create(dir=d, pre=b"aa", suf=b".txt"))
764 with self.assertRaises(TypeError):
765 os.rmdir(self.do_create(dir=d, pre="aa", suf=b".txt"))
766 with self.assertRaises(TypeError):
767 os.rmdir(self.do_create(dir=d, pre=b"aa", suf=".txt"))
768 with self.assertRaises(TypeError):
769 os.rmdir(self.do_create(dir="", pre=b"aa", suf=b".txt"))
770
Guido van Rossum0e548712002-08-09 16:14:33 +0000771 def test_basic_many(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000772 # mkdtemp can create many directories (stochastic)
Guido van Rossum805365e2007-05-07 22:24:25 +0000773 extant = list(range(TEST_FILES))
Guido van Rossum0e548712002-08-09 16:14:33 +0000774 try:
775 for i in extant:
776 extant[i] = self.do_create(pre="aa")
777 finally:
778 for i in extant:
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000779 if(isinstance(i, str)):
Guido van Rossum0e548712002-08-09 16:14:33 +0000780 os.rmdir(i)
781
782 def test_choose_directory(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000783 # mkdtemp can create directories in a user-selected directory
Guido van Rossum0e548712002-08-09 16:14:33 +0000784 dir = tempfile.mkdtemp()
785 try:
786 os.rmdir(self.do_create(dir=dir))
Anthony Sottile370138b2019-09-09 08:54:34 -0700787 os.rmdir(self.do_create(dir=pathlib.Path(dir)))
Guido van Rossum0e548712002-08-09 16:14:33 +0000788 finally:
789 os.rmdir(dir)
790
791 def test_mode(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000792 # mkdtemp creates directories with the proper mode
Guido van Rossum0e548712002-08-09 16:14:33 +0000793
794 dir = self.do_create()
795 try:
796 mode = stat.S_IMODE(os.stat(dir).st_mode)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000797 mode &= 0o777 # Mask off sticky bits inherited from /tmp
798 expected = 0o700
Jesus Cea4791a242012-10-05 03:15:39 +0200799 if sys.platform == 'win32':
Tim Petersca3ac7f2002-08-09 18:13:51 +0000800 # There's no distinction among 'user', 'group' and 'world';
801 # replicate the 'user' bits.
802 user = expected >> 6
803 expected = user * (1 + 8 + 64)
804 self.assertEqual(mode, expected)
Guido van Rossum0e548712002-08-09 16:14:33 +0000805 finally:
806 os.rmdir(dir)
807
Eli Benderskyaa04f9a2013-09-13 05:28:20 -0700808 def test_collision_with_existing_file(self):
809 # mkdtemp tries another name when a file with
810 # the chosen name already exists
811 with _inside_empty_temp_dir(), \
812 _mock_candidate_names('aaa', 'aaa', 'bbb'):
813 file = tempfile.NamedTemporaryFile(delete=False)
814 file.close()
815 self.assertTrue(file.name.endswith('aaa'))
816 dir = tempfile.mkdtemp()
817 self.assertTrue(dir.endswith('bbb'))
818
819 def test_collision_with_existing_directory(self):
820 # mkdtemp tries another name when a directory with
821 # the chosen name already exists
822 with _inside_empty_temp_dir(), \
823 _mock_candidate_names('aaa', 'aaa', 'bbb'):
824 dir1 = tempfile.mkdtemp()
825 self.assertTrue(dir1.endswith('aaa'))
826 dir2 = tempfile.mkdtemp()
827 self.assertTrue(dir2.endswith('bbb'))
828
Eric L9c792742021-03-03 21:36:22 +0100829 def test_for_tempdir_is_bytes_issue40701_api_warts(self):
830 orig_tempdir = tempfile.tempdir
831 self.assertIsInstance(tempfile.tempdir, (str, type(None)))
832 try:
833 path = tempfile.mkdtemp()
834 os.rmdir(path)
835 self.assertIsInstance(path, str)
836 tempfile.tempdir = tempfile.gettempdirb()
837 self.assertIsInstance(tempfile.tempdir, bytes)
838 self.assertIsInstance(tempfile.gettempdir(), str)
839 self.assertIsInstance(tempfile.gettempdirb(), bytes)
840 path = tempfile.mkdtemp()
841 os.rmdir(path)
842 self.assertIsInstance(path, bytes)
843 path = tempfile.mkdtemp(suffix='-dir')
844 os.rmdir(path)
845 self.assertIsInstance(path, str)
846 path = tempfile.mkdtemp(prefix='test-mkdtemp-')
847 os.rmdir(path)
848 self.assertIsInstance(path, str)
849 path = tempfile.mkdtemp(dir=tempfile.gettempdir())
850 os.rmdir(path)
851 self.assertIsInstance(path, str)
852 finally:
853 tempfile.tempdir = orig_tempdir
854
Guido van Rossum0e548712002-08-09 16:14:33 +0000855
Antoine Pitroueab2a502012-03-10 16:34:40 +0100856class TestMktemp(BaseTestCase):
Guido van Rossum0e548712002-08-09 16:14:33 +0000857 """Test mktemp()."""
858
859 # For safety, all use of mktemp must occur in a private directory.
860 # We must also suppress the RuntimeWarning it generates.
861 def setUp(self):
862 self.dir = tempfile.mkdtemp()
Brett Cannone1adece2010-03-20 22:19:55 +0000863 super().setUp()
Guido van Rossum0e548712002-08-09 16:14:33 +0000864
865 def tearDown(self):
866 if self.dir:
867 os.rmdir(self.dir)
868 self.dir = None
Brett Cannone1adece2010-03-20 22:19:55 +0000869 super().tearDown()
Guido van Rossum0e548712002-08-09 16:14:33 +0000870
871 class mktemped:
872 _unlink = os.unlink
873 _bflags = tempfile._bin_openflags
874
875 def __init__(self, dir, pre, suf):
876 self.name = tempfile.mktemp(dir=dir, prefix=pre, suffix=suf)
877 # Create the file. This will raise an exception if it's
878 # mysteriously appeared in the meanwhile.
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000879 os.close(os.open(self.name, self._bflags, 0o600))
Guido van Rossum0e548712002-08-09 16:14:33 +0000880
881 def __del__(self):
882 self._unlink(self.name)
883
884 def do_create(self, pre="", suf=""):
Antoine Pitrou8cd8d5e2012-03-10 16:20:24 +0100885 file = self.mktemped(self.dir, pre, suf)
Guido van Rossum0e548712002-08-09 16:14:33 +0000886
887 self.nameCheck(file.name, self.dir, pre, suf)
888 return file
889
890 def test_basic(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000891 # mktemp can choose usable file names
Guido van Rossum0e548712002-08-09 16:14:33 +0000892 self.do_create()
893 self.do_create(pre="a")
894 self.do_create(suf="b")
895 self.do_create(pre="a", suf="b")
896 self.do_create(pre="aa", suf=".txt")
897
898 def test_many(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000899 # mktemp can choose many usable file names (stochastic)
Guido van Rossum805365e2007-05-07 22:24:25 +0000900 extant = list(range(TEST_FILES))
Guido van Rossum0e548712002-08-09 16:14:33 +0000901 for i in extant:
902 extant[i] = self.do_create(pre="aa")
Serhiy Storchaka462c1f02021-09-08 18:08:57 +0300903 del extant
904 support.gc_collect() # For PyPy or other GCs.
Guido van Rossum0e548712002-08-09 16:14:33 +0000905
Fred Drake8bec4832002-11-22 20:13:43 +0000906## def test_warning(self):
907## # mktemp issues a warning when used
908## warnings.filterwarnings("error",
909## category=RuntimeWarning,
910## message="mktemp")
911## self.assertRaises(RuntimeWarning,
912## tempfile.mktemp, dir=self.dir)
Guido van Rossum0e548712002-08-09 16:14:33 +0000913
Guido van Rossum0e548712002-08-09 16:14:33 +0000914
915# We test _TemporaryFileWrapper by testing NamedTemporaryFile.
916
917
Antoine Pitroueab2a502012-03-10 16:34:40 +0100918class TestNamedTemporaryFile(BaseTestCase):
Guido van Rossum0e548712002-08-09 16:14:33 +0000919 """Test NamedTemporaryFile()."""
920
Guido van Rossumd8faa362007-04-27 19:54:29 +0000921 def do_create(self, dir=None, pre="", suf="", delete=True):
Guido van Rossum0e548712002-08-09 16:14:33 +0000922 if dir is None:
923 dir = tempfile.gettempdir()
Antoine Pitrou8cd8d5e2012-03-10 16:20:24 +0100924 file = tempfile.NamedTemporaryFile(dir=dir, prefix=pre, suffix=suf,
925 delete=delete)
Guido van Rossum0e548712002-08-09 16:14:33 +0000926
927 self.nameCheck(file.name, dir, pre, suf)
928 return file
929
930
931 def test_basic(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000932 # NamedTemporaryFile can create files
Guido van Rossum0e548712002-08-09 16:14:33 +0000933 self.do_create()
934 self.do_create(pre="a")
935 self.do_create(suf="b")
936 self.do_create(pre="a", suf="b")
937 self.do_create(pre="aa", suf=".txt")
938
Antoine Pitrou17c93262013-12-21 22:14:56 +0100939 def test_method_lookup(self):
940 # Issue #18879: Looking up a temporary file method should keep it
941 # alive long enough.
942 f = self.do_create()
943 wr = weakref.ref(f)
944 write = f.write
945 write2 = f.write
946 del f
947 write(b'foo')
948 del write
949 write2(b'bar')
950 del write2
951 if support.check_impl_detail(cpython=True):
952 # No reference cycle was created.
953 self.assertIsNone(wr())
954
Serhiy Storchaka56cefa62015-03-19 15:23:15 +0200955 def test_iter(self):
956 # Issue #23700: getting iterator from a temporary file should keep
957 # it alive as long as it's being iterated over
958 lines = [b'spam\n', b'eggs\n', b'beans\n']
959 def make_file():
960 f = tempfile.NamedTemporaryFile(mode='w+b')
961 f.write(b''.join(lines))
962 f.seek(0)
963 return f
964 for i, l in enumerate(make_file()):
965 self.assertEqual(l, lines[i])
966 self.assertEqual(i, len(lines) - 1)
967
Guido van Rossum0e548712002-08-09 16:14:33 +0000968 def test_creates_named(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000969 # NamedTemporaryFile creates files with names
Guido van Rossum0e548712002-08-09 16:14:33 +0000970 f = tempfile.NamedTemporaryFile()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000971 self.assertTrue(os.path.exists(f.name),
Guido van Rossum0e548712002-08-09 16:14:33 +0000972 "NamedTemporaryFile %s does not exist" % f.name)
973
974 def test_del_on_close(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +0000975 # A NamedTemporaryFile is deleted when closed
Guido van Rossum0e548712002-08-09 16:14:33 +0000976 dir = tempfile.mkdtemp()
977 try:
Serhiy Storchaka5b10b982019-03-05 10:06:26 +0200978 with tempfile.NamedTemporaryFile(dir=dir) as f:
979 f.write(b'blat')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000980 self.assertFalse(os.path.exists(f.name),
Guido van Rossum0e548712002-08-09 16:14:33 +0000981 "NamedTemporaryFile %s exists after close" % f.name)
982 finally:
983 os.rmdir(dir)
984
Guido van Rossumd8faa362007-04-27 19:54:29 +0000985 def test_dis_del_on_close(self):
986 # Tests that delete-on-close can be disabled
987 dir = tempfile.mkdtemp()
988 tmp = None
989 try:
990 f = tempfile.NamedTemporaryFile(dir=dir, delete=False)
991 tmp = f.name
Guido van Rossumec42ffd2007-08-27 23:40:36 +0000992 f.write(b'blat')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000993 f.close()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000994 self.assertTrue(os.path.exists(f.name),
Guido van Rossumd8faa362007-04-27 19:54:29 +0000995 "NamedTemporaryFile %s missing after close" % f.name)
996 finally:
997 if tmp is not None:
998 os.unlink(tmp)
999 os.rmdir(dir)
1000
Guido van Rossum0e548712002-08-09 16:14:33 +00001001 def test_multiple_close(self):
Guido van Rossum8ccd9b62002-08-22 20:02:03 +00001002 # A NamedTemporaryFile can be closed many times without error
Guido van Rossum0e548712002-08-09 16:14:33 +00001003 f = tempfile.NamedTemporaryFile()
Guido van Rossumec42ffd2007-08-27 23:40:36 +00001004 f.write(b'abc\n')
Guido van Rossum0e548712002-08-09 16:14:33 +00001005 f.close()
Antoine Pitrou8cd8d5e2012-03-10 16:20:24 +01001006 f.close()
1007 f.close()
Guido van Rossum0e548712002-08-09 16:14:33 +00001008
Christian Heimes3ecfea712008-02-09 20:51:34 +00001009 def test_context_manager(self):
1010 # A NamedTemporaryFile can be used as a context manager
1011 with tempfile.NamedTemporaryFile() as f:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001012 self.assertTrue(os.path.exists(f.name))
1013 self.assertFalse(os.path.exists(f.name))
Christian Heimes3ecfea712008-02-09 20:51:34 +00001014 def use_closed():
1015 with f:
1016 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001017 self.assertRaises(ValueError, use_closed)
Christian Heimes3ecfea712008-02-09 20:51:34 +00001018
Victor Stinner1f99f9d2014-03-25 09:18:04 +01001019 def test_no_leak_fd(self):
Victor Stinner87d13ea2014-03-25 18:19:17 +01001020 # Issue #21058: don't leak file descriptor when io.open() fails
Victor Stinner1f99f9d2014-03-25 09:18:04 +01001021 closed = []
Victor Stinnerc61c1702014-07-29 01:13:39 +02001022 os_close = os.close
Victor Stinner1f99f9d2014-03-25 09:18:04 +01001023 def close(fd):
1024 closed.append(fd)
Victor Stinnerc61c1702014-07-29 01:13:39 +02001025 os_close(fd)
Victor Stinner1f99f9d2014-03-25 09:18:04 +01001026
1027 with mock.patch('os.close', side_effect=close):
1028 with mock.patch('io.open', side_effect=ValueError):
1029 self.assertRaises(ValueError, tempfile.NamedTemporaryFile)
1030 self.assertEqual(len(closed), 1)
1031
Martin Panter7869a222016-02-28 05:22:20 +00001032 def test_bad_mode(self):
1033 dir = tempfile.mkdtemp()
Hai Shi0c4f0f32020-06-30 21:46:31 +08001034 self.addCleanup(os_helper.rmtree, dir)
Martin Panter7869a222016-02-28 05:22:20 +00001035 with self.assertRaises(ValueError):
1036 tempfile.NamedTemporaryFile(mode='wr', dir=dir)
1037 with self.assertRaises(TypeError):
1038 tempfile.NamedTemporaryFile(mode=2, dir=dir)
1039 self.assertEqual(os.listdir(dir), [])
Guido van Rossum0e548712002-08-09 16:14:33 +00001040
Martin Panter7869a222016-02-28 05:22:20 +00001041 # How to test the mode and bufsize parameters?
Guido van Rossum0e548712002-08-09 16:14:33 +00001042
Antoine Pitroueab2a502012-03-10 16:34:40 +01001043class TestSpooledTemporaryFile(BaseTestCase):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001044 """Test SpooledTemporaryFile()."""
1045
1046 def do_create(self, max_size=0, dir=None, pre="", suf=""):
1047 if dir is None:
1048 dir = tempfile.gettempdir()
Antoine Pitrou8cd8d5e2012-03-10 16:20:24 +01001049 file = tempfile.SpooledTemporaryFile(max_size=max_size, dir=dir, prefix=pre, suffix=suf)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001050
1051 return file
1052
1053
1054 def test_basic(self):
1055 # SpooledTemporaryFile can create files
1056 f = self.do_create()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001057 self.assertFalse(f._rolled)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001058 f = self.do_create(max_size=100, pre="a", suf=".txt")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001059 self.assertFalse(f._rolled)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001060
1061 def test_del_on_close(self):
1062 # A SpooledTemporaryFile is deleted when closed
1063 dir = tempfile.mkdtemp()
1064 try:
1065 f = tempfile.SpooledTemporaryFile(max_size=10, dir=dir)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001066 self.assertFalse(f._rolled)
Guido van Rossum39478e82007-08-27 17:23:59 +00001067 f.write(b'blat ' * 5)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001068 self.assertTrue(f._rolled)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001069 filename = f.name
1070 f.close()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001071 self.assertFalse(isinstance(filename, str) and os.path.exists(filename),
Guido van Rossumd8faa362007-04-27 19:54:29 +00001072 "SpooledTemporaryFile %s exists after close" % filename)
1073 finally:
1074 os.rmdir(dir)
1075
1076 def test_rewrite_small(self):
1077 # A SpooledTemporaryFile can be written to multiple within the max_size
1078 f = self.do_create(max_size=30)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001079 self.assertFalse(f._rolled)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001080 for i in range(5):
1081 f.seek(0, 0)
Guido van Rossum39478e82007-08-27 17:23:59 +00001082 f.write(b'x' * 20)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001083 self.assertFalse(f._rolled)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001084
1085 def test_write_sequential(self):
1086 # A SpooledTemporaryFile should hold exactly max_size bytes, and roll
1087 # over afterward
1088 f = self.do_create(max_size=30)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001089 self.assertFalse(f._rolled)
Guido van Rossum39478e82007-08-27 17:23:59 +00001090 f.write(b'x' * 20)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001091 self.assertFalse(f._rolled)
Guido van Rossum39478e82007-08-27 17:23:59 +00001092 f.write(b'x' * 10)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001093 self.assertFalse(f._rolled)
Guido van Rossum39478e82007-08-27 17:23:59 +00001094 f.write(b'x')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001095 self.assertTrue(f._rolled)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001096
R David Murrayd89ee792011-03-14 09:55:46 -04001097 def test_writelines(self):
1098 # Verify writelines with a SpooledTemporaryFile
1099 f = self.do_create()
1100 f.writelines((b'x', b'y', b'z'))
Inada Naoki485e7152020-04-17 15:56:35 +09001101 pos = f.seek(0)
1102 self.assertEqual(pos, 0)
R David Murrayd89ee792011-03-14 09:55:46 -04001103 buf = f.read()
1104 self.assertEqual(buf, b'xyz')
1105
1106 def test_writelines_sequential(self):
1107 # A SpooledTemporaryFile should hold exactly max_size bytes, and roll
1108 # over afterward
1109 f = self.do_create(max_size=35)
1110 f.writelines((b'x' * 20, b'x' * 10, b'x' * 5))
1111 self.assertFalse(f._rolled)
1112 f.write(b'x')
1113 self.assertTrue(f._rolled)
1114
Guido van Rossumd8faa362007-04-27 19:54:29 +00001115 def test_sparse(self):
1116 # A SpooledTemporaryFile that is written late in the file will extend
1117 # when that occurs
1118 f = self.do_create(max_size=30)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001119 self.assertFalse(f._rolled)
Inada Naoki485e7152020-04-17 15:56:35 +09001120 pos = f.seek(100, 0)
1121 self.assertEqual(pos, 100)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001122 self.assertFalse(f._rolled)
Guido van Rossum39478e82007-08-27 17:23:59 +00001123 f.write(b'x')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001124 self.assertTrue(f._rolled)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001125
1126 def test_fileno(self):
1127 # A SpooledTemporaryFile should roll over to a real file on fileno()
1128 f = self.do_create(max_size=30)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001129 self.assertFalse(f._rolled)
1130 self.assertTrue(f.fileno() > 0)
1131 self.assertTrue(f._rolled)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001132
Christian Heimes3ecfea712008-02-09 20:51:34 +00001133 def test_multiple_close_before_rollover(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001134 # A SpooledTemporaryFile can be closed many times without error
1135 f = tempfile.SpooledTemporaryFile()
Guido van Rossum39478e82007-08-27 17:23:59 +00001136 f.write(b'abc\n')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001137 self.assertFalse(f._rolled)
Christian Heimes3ecfea712008-02-09 20:51:34 +00001138 f.close()
Antoine Pitrou8cd8d5e2012-03-10 16:20:24 +01001139 f.close()
1140 f.close()
Christian Heimes3ecfea712008-02-09 20:51:34 +00001141
1142 def test_multiple_close_after_rollover(self):
1143 # A SpooledTemporaryFile can be closed many times without error
1144 f = tempfile.SpooledTemporaryFile(max_size=1)
1145 f.write(b'abc\n')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001146 self.assertTrue(f._rolled)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001147 f.close()
Antoine Pitrou8cd8d5e2012-03-10 16:20:24 +01001148 f.close()
1149 f.close()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001150
1151 def test_bound_methods(self):
1152 # It should be OK to steal a bound method from a SpooledTemporaryFile
1153 # and use it independently; when the file rolls over, those bound
1154 # methods should continue to function
1155 f = self.do_create(max_size=30)
1156 read = f.read
1157 write = f.write
1158 seek = f.seek
1159
Guido van Rossum39478e82007-08-27 17:23:59 +00001160 write(b"a" * 35)
1161 write(b"b" * 35)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001162 seek(0, 0)
Guido van Rossum9a634702007-07-09 10:24:45 +00001163 self.assertEqual(read(70), b'a'*35 + b'b'*35)
1164
Serhiy Storchakabbbbe8e2013-02-09 12:21:14 +02001165 def test_properties(self):
1166 f = tempfile.SpooledTemporaryFile(max_size=10)
1167 f.write(b'x' * 10)
1168 self.assertFalse(f._rolled)
1169 self.assertEqual(f.mode, 'w+b')
1170 self.assertIsNone(f.name)
1171 with self.assertRaises(AttributeError):
1172 f.newlines
1173 with self.assertRaises(AttributeError):
1174 f.encoding
sth825aab92018-05-23 07:07:01 +02001175 with self.assertRaises(AttributeError):
1176 f.errors
Serhiy Storchakabbbbe8e2013-02-09 12:21:14 +02001177
1178 f.write(b'x')
1179 self.assertTrue(f._rolled)
1180 self.assertEqual(f.mode, 'rb+')
1181 self.assertIsNotNone(f.name)
1182 with self.assertRaises(AttributeError):
1183 f.newlines
1184 with self.assertRaises(AttributeError):
1185 f.encoding
sth825aab92018-05-23 07:07:01 +02001186 with self.assertRaises(AttributeError):
1187 f.errors
Serhiy Storchakabbbbe8e2013-02-09 12:21:14 +02001188
Guido van Rossum9a634702007-07-09 10:24:45 +00001189 def test_text_mode(self):
1190 # Creating a SpooledTemporaryFile with a text mode should produce
1191 # a file object reading and writing (Unicode) text strings.
Inada Naokiea9835c2019-11-27 22:22:06 +09001192 f = tempfile.SpooledTemporaryFile(mode='w+', max_size=10,
1193 encoding="utf-8")
Guido van Rossum9a634702007-07-09 10:24:45 +00001194 f.write("abc\n")
1195 f.seek(0)
1196 self.assertEqual(f.read(), "abc\n")
1197 f.write("def\n")
1198 f.seek(0)
1199 self.assertEqual(f.read(), "abc\ndef\n")
Serhiy Storchakabbbbe8e2013-02-09 12:21:14 +02001200 self.assertFalse(f._rolled)
1201 self.assertEqual(f.mode, 'w+')
1202 self.assertIsNone(f.name)
Inada Naokiea9835c2019-11-27 22:22:06 +09001203 self.assertEqual(f.newlines, os.linesep)
1204 self.assertEqual(f.encoding, "utf-8")
1205 self.assertEqual(f.errors, "strict")
Serhiy Storchakabbbbe8e2013-02-09 12:21:14 +02001206
Guido van Rossum9a634702007-07-09 10:24:45 +00001207 f.write("xyzzy\n")
1208 f.seek(0)
1209 self.assertEqual(f.read(), "abc\ndef\nxyzzy\n")
Amaury Forgeot d'Arc7d0bddd2009-11-30 00:08:56 +00001210 # Check that Ctrl+Z doesn't truncate the file
1211 f.write("foo\x1abar\n")
1212 f.seek(0)
1213 self.assertEqual(f.read(), "abc\ndef\nxyzzy\nfoo\x1abar\n")
Serhiy Storchakabbbbe8e2013-02-09 12:21:14 +02001214 self.assertTrue(f._rolled)
1215 self.assertEqual(f.mode, 'w+')
1216 self.assertIsNotNone(f.name)
Serhiy Storchaka497cee42013-02-10 14:43:46 +02001217 self.assertEqual(f.newlines, os.linesep)
Inada Naokiea9835c2019-11-27 22:22:06 +09001218 self.assertEqual(f.encoding, "utf-8")
1219 self.assertEqual(f.errors, "strict")
Guido van Rossum9a634702007-07-09 10:24:45 +00001220
Guido van Rossumf0c74162007-08-28 03:29:45 +00001221 def test_text_newline_and_encoding(self):
1222 f = tempfile.SpooledTemporaryFile(mode='w+', max_size=10,
sth825aab92018-05-23 07:07:01 +02001223 newline='', encoding='utf-8',
1224 errors='ignore')
Guido van Rossumf0c74162007-08-28 03:29:45 +00001225 f.write("\u039B\r\n")
1226 f.seek(0)
1227 self.assertEqual(f.read(), "\u039B\r\n")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001228 self.assertFalse(f._rolled)
Serhiy Storchakabbbbe8e2013-02-09 12:21:14 +02001229 self.assertEqual(f.mode, 'w+')
1230 self.assertIsNone(f.name)
Inada Naokiea9835c2019-11-27 22:22:06 +09001231 self.assertIsNotNone(f.newlines)
1232 self.assertEqual(f.encoding, "utf-8")
1233 self.assertEqual(f.errors, "ignore")
Guido van Rossumf0c74162007-08-28 03:29:45 +00001234
Inada Naokiea9835c2019-11-27 22:22:06 +09001235 f.write("\u039C" * 10 + "\r\n")
1236 f.write("\u039D" * 20)
Guido van Rossumf0c74162007-08-28 03:29:45 +00001237 f.seek(0)
Inada Naokiea9835c2019-11-27 22:22:06 +09001238 self.assertEqual(f.read(),
1239 "\u039B\r\n" + ("\u039C" * 10) + "\r\n" + ("\u039D" * 20))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001240 self.assertTrue(f._rolled)
Serhiy Storchakabbbbe8e2013-02-09 12:21:14 +02001241 self.assertEqual(f.mode, 'w+')
1242 self.assertIsNotNone(f.name)
1243 self.assertIsNotNone(f.newlines)
1244 self.assertEqual(f.encoding, 'utf-8')
sth825aab92018-05-23 07:07:01 +02001245 self.assertEqual(f.errors, 'ignore')
Guido van Rossumd8faa362007-04-27 19:54:29 +00001246
Christian Heimes3ecfea712008-02-09 20:51:34 +00001247 def test_context_manager_before_rollover(self):
1248 # A SpooledTemporaryFile can be used as a context manager
1249 with tempfile.SpooledTemporaryFile(max_size=1) as f:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001250 self.assertFalse(f._rolled)
1251 self.assertFalse(f.closed)
1252 self.assertTrue(f.closed)
Christian Heimes3ecfea712008-02-09 20:51:34 +00001253 def use_closed():
1254 with f:
1255 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001256 self.assertRaises(ValueError, use_closed)
Christian Heimes3ecfea712008-02-09 20:51:34 +00001257
1258 def test_context_manager_during_rollover(self):
1259 # A SpooledTemporaryFile can be used as a context manager
1260 with tempfile.SpooledTemporaryFile(max_size=1) as f:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001261 self.assertFalse(f._rolled)
Christian Heimes3ecfea712008-02-09 20:51:34 +00001262 f.write(b'abc\n')
1263 f.flush()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001264 self.assertTrue(f._rolled)
1265 self.assertFalse(f.closed)
1266 self.assertTrue(f.closed)
Christian Heimes3ecfea712008-02-09 20:51:34 +00001267 def use_closed():
1268 with f:
1269 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001270 self.assertRaises(ValueError, use_closed)
Christian Heimes3ecfea712008-02-09 20:51:34 +00001271
1272 def test_context_manager_after_rollover(self):
1273 # A SpooledTemporaryFile can be used as a context manager
1274 f = tempfile.SpooledTemporaryFile(max_size=1)
1275 f.write(b'abc\n')
1276 f.flush()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001277 self.assertTrue(f._rolled)
Christian Heimes3ecfea712008-02-09 20:51:34 +00001278 with f:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001279 self.assertFalse(f.closed)
1280 self.assertTrue(f.closed)
Christian Heimes3ecfea712008-02-09 20:51:34 +00001281 def use_closed():
1282 with f:
1283 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001284 self.assertRaises(ValueError, use_closed)
Christian Heimes3ecfea712008-02-09 20:51:34 +00001285
Antoine Pitrou0e86a582011-11-25 18:03:09 +01001286 def test_truncate_with_size_parameter(self):
1287 # A SpooledTemporaryFile can be truncated to zero size
1288 f = tempfile.SpooledTemporaryFile(max_size=10)
1289 f.write(b'abcdefg\n')
1290 f.seek(0)
1291 f.truncate()
1292 self.assertFalse(f._rolled)
1293 self.assertEqual(f._file.getvalue(), b'')
1294 # A SpooledTemporaryFile can be truncated to a specific size
1295 f = tempfile.SpooledTemporaryFile(max_size=10)
1296 f.write(b'abcdefg\n')
1297 f.truncate(4)
1298 self.assertFalse(f._rolled)
1299 self.assertEqual(f._file.getvalue(), b'abcd')
1300 # A SpooledTemporaryFile rolls over if truncated to large size
1301 f = tempfile.SpooledTemporaryFile(max_size=10)
1302 f.write(b'abcdefg\n')
1303 f.truncate(20)
1304 self.assertTrue(f._rolled)
Anthony Sottile8377cd42019-02-25 14:32:27 -08001305 self.assertEqual(os.fstat(f.fileno()).st_size, 20)
Christian Heimes3ecfea712008-02-09 20:51:34 +00001306
Batuhan TaĹźkaya09c482f2019-12-30 19:08:08 +03001307 def test_class_getitem(self):
Guido van Rossum48b069a2020-04-07 09:50:06 -07001308 self.assertIsInstance(tempfile.SpooledTemporaryFile[bytes],
1309 types.GenericAlias)
Guido van Rossum0e548712002-08-09 16:14:33 +00001310
Guido van Rossum8ccd9b62002-08-22 20:02:03 +00001311if tempfile.NamedTemporaryFile is not tempfile.TemporaryFile:
Antoine Pitroueab2a502012-03-10 16:34:40 +01001312
1313 class TestTemporaryFile(BaseTestCase):
1314 """Test TemporaryFile()."""
1315
1316 def test_basic(self):
1317 # TemporaryFile can create files
1318 # No point in testing the name params - the file has no name.
1319 tempfile.TemporaryFile()
1320
1321 def test_has_no_name(self):
1322 # TemporaryFile creates files with no names (on this system)
1323 dir = tempfile.mkdtemp()
1324 f = tempfile.TemporaryFile(dir=dir)
1325 f.write(b'blat')
1326
1327 # Sneaky: because this file has no name, it should not prevent
1328 # us from removing the directory it was created in.
1329 try:
1330 os.rmdir(dir)
1331 except:
1332 # cleanup
1333 f.close()
1334 os.rmdir(dir)
1335 raise
1336
1337 def test_multiple_close(self):
1338 # A TemporaryFile can be closed many times without error
1339 f = tempfile.TemporaryFile()
1340 f.write(b'abc\n')
1341 f.close()
1342 f.close()
1343 f.close()
1344
1345 # How to test the mode and bufsize parameters?
1346 def test_mode_and_encoding(self):
1347
1348 def roundtrip(input, *args, **kwargs):
1349 with tempfile.TemporaryFile(*args, **kwargs) as fileobj:
1350 fileobj.write(input)
1351 fileobj.seek(0)
1352 self.assertEqual(input, fileobj.read())
1353
1354 roundtrip(b"1234", "w+b")
1355 roundtrip("abdc\n", "w+")
1356 roundtrip("\u039B", "w+", encoding="utf-16")
1357 roundtrip("foo\r\n", "w+", newline="")
Guido van Rossum0e548712002-08-09 16:14:33 +00001358
Victor Stinner1f99f9d2014-03-25 09:18:04 +01001359 def test_no_leak_fd(self):
1360 # Issue #21058: don't leak file descriptor when io.open() fails
1361 closed = []
Victor Stinnerc61c1702014-07-29 01:13:39 +02001362 os_close = os.close
Victor Stinner1f99f9d2014-03-25 09:18:04 +01001363 def close(fd):
1364 closed.append(fd)
Victor Stinnerc61c1702014-07-29 01:13:39 +02001365 os_close(fd)
Victor Stinner1f99f9d2014-03-25 09:18:04 +01001366
1367 with mock.patch('os.close', side_effect=close):
1368 with mock.patch('io.open', side_effect=ValueError):
1369 self.assertRaises(ValueError, tempfile.TemporaryFile)
1370 self.assertEqual(len(closed), 1)
1371
1372
Nick Coghlan543af752010-10-24 11:23:25 +00001373
1374# Helper for test_del_on_shutdown
1375class NulledModules:
1376 def __init__(self, *modules):
1377 self.refs = [mod.__dict__ for mod in modules]
1378 self.contents = [ref.copy() for ref in self.refs]
1379
1380 def __enter__(self):
1381 for d in self.refs:
1382 for key in d:
1383 d[key] = None
1384
1385 def __exit__(self, *exc_info):
1386 for d, c in zip(self.refs, self.contents):
1387 d.clear()
1388 d.update(c)
1389
CAM Gerlachbd2fa3c2021-03-14 13:06:56 -05001390
Antoine Pitroueab2a502012-03-10 16:34:40 +01001391class TestTemporaryDirectory(BaseTestCase):
Nick Coghlan543af752010-10-24 11:23:25 +00001392 """Test TemporaryDirectory()."""
1393
CAM Gerlachbd2fa3c2021-03-14 13:06:56 -05001394 def do_create(self, dir=None, pre="", suf="", recurse=1, dirs=1, files=1,
1395 ignore_cleanup_errors=False):
Nick Coghlan543af752010-10-24 11:23:25 +00001396 if dir is None:
1397 dir = tempfile.gettempdir()
CAM Gerlachbd2fa3c2021-03-14 13:06:56 -05001398 tmp = tempfile.TemporaryDirectory(
1399 dir=dir, prefix=pre, suffix=suf,
1400 ignore_cleanup_errors=ignore_cleanup_errors)
Nick Coghlan543af752010-10-24 11:23:25 +00001401 self.nameCheck(tmp.name, dir, pre, suf)
Serhiy Storchakae9b51c02019-05-31 11:30:37 +03001402 self.do_create2(tmp.name, recurse, dirs, files)
Nick Coghlan543af752010-10-24 11:23:25 +00001403 return tmp
1404
Serhiy Storchakae9b51c02019-05-31 11:30:37 +03001405 def do_create2(self, path, recurse=1, dirs=1, files=1):
1406 # Create subdirectories and some files
1407 if recurse:
1408 for i in range(dirs):
1409 name = os.path.join(path, "dir%d" % i)
1410 os.mkdir(name)
1411 self.do_create2(name, recurse-1, dirs, files)
1412 for i in range(files):
1413 with open(os.path.join(path, "test%d.txt" % i), "wb") as f:
1414 f.write(b"Hello world!")
1415
Nick Coghlan6b22f3f2010-12-12 15:24:21 +00001416 def test_mkdtemp_failure(self):
1417 # Check no additional exception if mkdtemp fails
1418 # Previously would raise AttributeError instead
Nick Coghlan3c54ea62010-12-13 03:02:43 +00001419 # (noted as part of Issue #10188)
1420 with tempfile.TemporaryDirectory() as nonexistent:
1421 pass
Serhiy Storchaka7451a722013-02-09 22:25:49 +02001422 with self.assertRaises(FileNotFoundError) as cm:
Nick Coghlan3c54ea62010-12-13 03:02:43 +00001423 tempfile.TemporaryDirectory(dir=nonexistent)
Serhiy Storchaka7451a722013-02-09 22:25:49 +02001424 self.assertEqual(cm.exception.errno, errno.ENOENT)
Nick Coghlan6b22f3f2010-12-12 15:24:21 +00001425
Nick Coghlan543af752010-10-24 11:23:25 +00001426 def test_explicit_cleanup(self):
1427 # A TemporaryDirectory is deleted when cleaned up
1428 dir = tempfile.mkdtemp()
1429 try:
1430 d = self.do_create(dir=dir)
1431 self.assertTrue(os.path.exists(d.name),
1432 "TemporaryDirectory %s does not exist" % d.name)
1433 d.cleanup()
1434 self.assertFalse(os.path.exists(d.name),
1435 "TemporaryDirectory %s exists after cleanup" % d.name)
1436 finally:
1437 os.rmdir(dir)
1438
CAM Gerlachbd2fa3c2021-03-14 13:06:56 -05001439 def test_explict_cleanup_ignore_errors(self):
1440 """Test that cleanup doesn't return an error when ignoring them."""
1441 with tempfile.TemporaryDirectory() as working_dir:
1442 temp_dir = self.do_create(
1443 dir=working_dir, ignore_cleanup_errors=True)
1444 temp_path = pathlib.Path(temp_dir.name)
1445 self.assertTrue(temp_path.exists(),
1446 f"TemporaryDirectory {temp_path!s} does not exist")
1447 with open(temp_path / "a_file.txt", "w+t") as open_file:
1448 open_file.write("Hello world!\n")
1449 temp_dir.cleanup()
1450 self.assertEqual(len(list(temp_path.glob("*"))),
1451 int(sys.platform.startswith("win")),
1452 "Unexpected number of files in "
1453 f"TemporaryDirectory {temp_path!s}")
1454 self.assertEqual(
1455 temp_path.exists(),
1456 sys.platform.startswith("win"),
Christian Clausscfca4a62021-10-07 17:49:47 +02001457 f"TemporaryDirectory {temp_path!s} existence state unexpected")
CAM Gerlachbd2fa3c2021-03-14 13:06:56 -05001458 temp_dir.cleanup()
1459 self.assertFalse(
1460 temp_path.exists(),
1461 f"TemporaryDirectory {temp_path!s} exists after cleanup")
1462
Hai Shi0c4f0f32020-06-30 21:46:31 +08001463 @os_helper.skip_unless_symlink
Charles-François Natalidef35432011-07-29 18:59:24 +02001464 def test_cleanup_with_symlink_to_a_directory(self):
1465 # cleanup() should not follow symlinks to directories (issue #12464)
1466 d1 = self.do_create()
Serhiy Storchaka99e033b2014-01-27 11:18:27 +02001467 d2 = self.do_create(recurse=0)
Charles-François Natalidef35432011-07-29 18:59:24 +02001468
1469 # Symlink d1/foo -> d2
1470 os.symlink(d2.name, os.path.join(d1.name, "foo"))
1471
1472 # This call to cleanup() should not follow the "foo" symlink
1473 d1.cleanup()
1474
1475 self.assertFalse(os.path.exists(d1.name),
1476 "TemporaryDirectory %s exists after cleanup" % d1.name)
1477 self.assertTrue(os.path.exists(d2.name),
1478 "Directory pointed to by a symlink was deleted")
Serhiy Storchakae9b51c02019-05-31 11:30:37 +03001479 self.assertEqual(os.listdir(d2.name), ['test0.txt'],
Charles-François Natalidef35432011-07-29 18:59:24 +02001480 "Contents of the directory pointed to by a symlink "
1481 "were deleted")
1482 d2.cleanup()
1483
Nick Coghlan543af752010-10-24 11:23:25 +00001484 @support.cpython_only
1485 def test_del_on_collection(self):
1486 # A TemporaryDirectory is deleted when garbage collected
1487 dir = tempfile.mkdtemp()
1488 try:
1489 d = self.do_create(dir=dir)
1490 name = d.name
1491 del d # Rely on refcounting to invoke __del__
1492 self.assertFalse(os.path.exists(name),
1493 "TemporaryDirectory %s exists after __del__" % name)
1494 finally:
1495 os.rmdir(dir)
1496
CAM Gerlachbd2fa3c2021-03-14 13:06:56 -05001497 @support.cpython_only
1498 def test_del_on_collection_ignore_errors(self):
1499 """Test that ignoring errors works when TemporaryDirectory is gced."""
1500 with tempfile.TemporaryDirectory() as working_dir:
1501 temp_dir = self.do_create(
1502 dir=working_dir, ignore_cleanup_errors=True)
1503 temp_path = pathlib.Path(temp_dir.name)
1504 self.assertTrue(temp_path.exists(),
1505 f"TemporaryDirectory {temp_path!s} does not exist")
1506 with open(temp_path / "a_file.txt", "w+t") as open_file:
1507 open_file.write("Hello world!\n")
1508 del temp_dir
1509 self.assertEqual(len(list(temp_path.glob("*"))),
1510 int(sys.platform.startswith("win")),
1511 "Unexpected number of files in "
1512 f"TemporaryDirectory {temp_path!s}")
1513 self.assertEqual(
1514 temp_path.exists(),
1515 sys.platform.startswith("win"),
Christian Clausscfca4a62021-10-07 17:49:47 +02001516 f"TemporaryDirectory {temp_path!s} existence state unexpected")
CAM Gerlachbd2fa3c2021-03-14 13:06:56 -05001517
Nick Coghlan543af752010-10-24 11:23:25 +00001518 def test_del_on_shutdown(self):
1519 # A TemporaryDirectory may be cleaned up during shutdown
Nick Coghlan6b22f3f2010-12-12 15:24:21 +00001520 with self.do_create() as dir:
Serhiy Storchakaa28632b2014-01-27 11:21:54 +02001521 for mod in ('builtins', 'os', 'shutil', 'sys', 'tempfile', 'warnings'):
Serhiy Storchaka99e033b2014-01-27 11:18:27 +02001522 code = """if True:
Serhiy Storchakaa28632b2014-01-27 11:21:54 +02001523 import builtins
Serhiy Storchaka99e033b2014-01-27 11:18:27 +02001524 import os
1525 import shutil
1526 import sys
1527 import tempfile
1528 import warnings
1529
1530 tmp = tempfile.TemporaryDirectory(dir={dir!r})
1531 sys.stdout.buffer.write(tmp.name.encode())
1532
1533 tmp2 = os.path.join(tmp.name, 'test_dir')
1534 os.mkdir(tmp2)
Serhiy Storchakae9b51c02019-05-31 11:30:37 +03001535 with open(os.path.join(tmp2, "test0.txt"), "w") as f:
Serhiy Storchaka99e033b2014-01-27 11:18:27 +02001536 f.write("Hello world!")
1537
1538 {mod}.tmp = tmp
1539
1540 warnings.filterwarnings("always", category=ResourceWarning)
1541 """.format(dir=dir, mod=mod)
1542 rc, out, err = script_helper.assert_python_ok("-c", code)
1543 tmp_name = out.decode().strip()
1544 self.assertFalse(os.path.exists(tmp_name),
1545 "TemporaryDirectory %s exists after cleanup" % tmp_name)
1546 err = err.decode('utf-8', 'backslashreplace')
1547 self.assertNotIn("Exception ", err)
Serhiy Storchakaa28632b2014-01-27 11:21:54 +02001548 self.assertIn("ResourceWarning: Implicitly cleaning up", err)
Nick Coghlan6b22f3f2010-12-12 15:24:21 +00001549
CAM Gerlachbd2fa3c2021-03-14 13:06:56 -05001550 def test_del_on_shutdown_ignore_errors(self):
1551 """Test ignoring errors works when a tempdir is gc'ed on shutdown."""
1552 with tempfile.TemporaryDirectory() as working_dir:
1553 code = """if True:
1554 import pathlib
1555 import sys
1556 import tempfile
1557 import warnings
1558
1559 temp_dir = tempfile.TemporaryDirectory(
1560 dir={working_dir!r}, ignore_cleanup_errors=True)
1561 sys.stdout.buffer.write(temp_dir.name.encode())
1562
1563 temp_dir_2 = pathlib.Path(temp_dir.name) / "test_dir"
1564 temp_dir_2.mkdir()
1565 with open(temp_dir_2 / "test0.txt", "w") as test_file:
1566 test_file.write("Hello world!")
1567 open_file = open(temp_dir_2 / "open_file.txt", "w")
1568 open_file.write("Hello world!")
1569
1570 warnings.filterwarnings("always", category=ResourceWarning)
1571 """.format(working_dir=working_dir)
1572 __, out, err = script_helper.assert_python_ok("-c", code)
1573 temp_path = pathlib.Path(out.decode().strip())
1574 self.assertEqual(len(list(temp_path.glob("*"))),
1575 int(sys.platform.startswith("win")),
1576 "Unexpected number of files in "
1577 f"TemporaryDirectory {temp_path!s}")
1578 self.assertEqual(
1579 temp_path.exists(),
1580 sys.platform.startswith("win"),
Christian Clausscfca4a62021-10-07 17:49:47 +02001581 f"TemporaryDirectory {temp_path!s} existence state unexpected")
CAM Gerlachbd2fa3c2021-03-14 13:06:56 -05001582 err = err.decode('utf-8', 'backslashreplace')
1583 self.assertNotIn("Exception", err)
1584 self.assertNotIn("Error", err)
1585 self.assertIn("ResourceWarning: Implicitly cleaning up", err)
1586
Serhiy Storchaka5e193ac2014-09-24 13:26:25 +03001587 def test_exit_on_shutdown(self):
1588 # Issue #22427
1589 with self.do_create() as dir:
1590 code = """if True:
1591 import sys
1592 import tempfile
1593 import warnings
1594
1595 def generator():
1596 with tempfile.TemporaryDirectory(dir={dir!r}) as tmp:
1597 yield tmp
1598 g = generator()
1599 sys.stdout.buffer.write(next(g).encode())
1600
1601 warnings.filterwarnings("always", category=ResourceWarning)
1602 """.format(dir=dir)
1603 rc, out, err = script_helper.assert_python_ok("-c", code)
1604 tmp_name = out.decode().strip()
1605 self.assertFalse(os.path.exists(tmp_name),
1606 "TemporaryDirectory %s exists after cleanup" % tmp_name)
1607 err = err.decode('utf-8', 'backslashreplace')
1608 self.assertNotIn("Exception ", err)
1609 self.assertIn("ResourceWarning: Implicitly cleaning up", err)
1610
Nick Coghlan6b22f3f2010-12-12 15:24:21 +00001611 def test_warnings_on_cleanup(self):
Serhiy Storchaka99e033b2014-01-27 11:18:27 +02001612 # ResourceWarning will be triggered by __del__
Nick Coghlan6b22f3f2010-12-12 15:24:21 +00001613 with self.do_create() as dir:
Serhiy Storchaka99e033b2014-01-27 11:18:27 +02001614 d = self.do_create(dir=dir, recurse=3)
1615 name = d.name
Nick Coghlan6b22f3f2010-12-12 15:24:21 +00001616
1617 # Check for the resource warning
Hai Shi0c4f0f32020-06-30 21:46:31 +08001618 with warnings_helper.check_warnings(('Implicitly',
1619 ResourceWarning),
1620 quiet=False):
Nick Coghlan6b22f3f2010-12-12 15:24:21 +00001621 warnings.filterwarnings("always", category=ResourceWarning)
Serhiy Storchaka99e033b2014-01-27 11:18:27 +02001622 del d
1623 support.gc_collect()
1624 self.assertFalse(os.path.exists(name),
1625 "TemporaryDirectory %s exists after __del__" % name)
Nick Coghlan543af752010-10-24 11:23:25 +00001626
1627 def test_multiple_close(self):
1628 # Can be cleaned-up many times without error
1629 d = self.do_create()
1630 d.cleanup()
Antoine Pitrou8cd8d5e2012-03-10 16:20:24 +01001631 d.cleanup()
1632 d.cleanup()
Nick Coghlan543af752010-10-24 11:23:25 +00001633
1634 def test_context_manager(self):
1635 # Can be used as a context manager
1636 d = self.do_create()
1637 with d as name:
1638 self.assertTrue(os.path.exists(name))
1639 self.assertEqual(name, d.name)
1640 self.assertFalse(os.path.exists(name))
1641
Serhiy Storchakae9b51c02019-05-31 11:30:37 +03001642 def test_modes(self):
1643 for mode in range(8):
1644 mode <<= 6
1645 with self.subTest(mode=format(mode, '03o')):
1646 d = self.do_create(recurse=3, dirs=2, files=2)
1647 with d:
1648 # Change files and directories mode recursively.
1649 for root, dirs, files in os.walk(d.name, topdown=False):
1650 for name in files:
1651 os.chmod(os.path.join(root, name), mode)
1652 os.chmod(root, mode)
1653 d.cleanup()
1654 self.assertFalse(os.path.exists(d.name))
1655
1656 @unittest.skipUnless(hasattr(os, 'chflags'), 'requires os.lchflags')
1657 def test_flags(self):
1658 flags = stat.UF_IMMUTABLE | stat.UF_NOUNLINK
1659 d = self.do_create(recurse=3, dirs=2, files=2)
1660 with d:
1661 # Change files and directories flags recursively.
1662 for root, dirs, files in os.walk(d.name, topdown=False):
1663 for name in files:
1664 os.chflags(os.path.join(root, name), flags)
1665 os.chflags(root, flags)
1666 d.cleanup()
1667 self.assertFalse(os.path.exists(d.name))
1668
Nick Coghlan543af752010-10-24 11:23:25 +00001669
Guido van Rossum0e548712002-08-09 16:14:33 +00001670if __name__ == "__main__":
Zachary Ware38c707e2015-04-13 15:00:43 -05001671 unittest.main()