1 # tempfile.py unit tests.
9 from test
import test_support
11 warnings
.filterwarnings("ignore",
12 category
=RuntimeWarning,
13 message
="mktemp", module
=__name__
)
15 if hasattr(os
, 'stat'):
21 has_textmode
= (tempfile
._text
_openflags
!= tempfile
._bin
_openflags
)
22 has_spawnl
= hasattr(os
, 'spawnl')
24 # TEST_FILES may need to be tweaked for systems depending on the maximum
25 # number of files that can be opened at one time (see ulimit -n)
26 if sys
.platform
in ('openbsd3', 'openbsd4'):
31 # This is organized as one test for each chunk of code in tempfile.py,
32 # in order of their appearance in the file. Testing which requires
33 # threads is not done here.
35 # Common functionality.
36 class TC(unittest
.TestCase
):
38 str_check
= re
.compile(r
"[a-zA-Z0-9_-]{6}$")
40 def failOnException(self
, what
, ei
=None):
43 self
.fail("%s raised %s: %s" % (what
, ei
[0], ei
[1]))
45 def nameCheck(self
, name
, dir, pre
, suf
):
46 (ndir
, nbase
) = os
.path
.split(name
)
47 npre
= nbase
[:len(pre
)]
48 nsuf
= nbase
[len(nbase
)-len(suf
):]
50 # check for equality of the absolute paths!
51 self
.assertEqual(os
.path
.abspath(ndir
), os
.path
.abspath(dir),
52 "file '%s' not in directory '%s'" % (name
, dir))
53 self
.assertEqual(npre
, pre
,
54 "file '%s' does not begin with '%s'" % (nbase
, pre
))
55 self
.assertEqual(nsuf
, suf
,
56 "file '%s' does not end with '%s'" % (nbase
, suf
))
58 nbase
= nbase
[len(pre
):len(nbase
)-len(suf
)]
59 self
.assertTrue(self
.str_check
.match(nbase
),
60 "random string '%s' does not match /^[a-zA-Z0-9_-]{6}$/"
65 class test_exports(TC
):
66 def test_exports(self
):
67 # There are no surprising symbols in the tempfile module
68 dict = tempfile
.__dict
__
71 "NamedTemporaryFile" : 1,
81 "SpooledTemporaryFile" : 1
86 if key
[0] != '_' and key
not in expected
:
88 self
.assertTrue(len(unexp
) == 0,
89 "unexpected keys: %s" % unexp
)
91 test_classes
.append(test_exports
)
94 class test__RandomNameSequence(TC
):
95 """Test the internal iterator object _RandomNameSequence."""
98 self
.r
= tempfile
._RandomNameSequence
()
100 def test_get_six_char_str(self
):
101 # _RandomNameSequence returns a six-character string
103 self
.nameCheck(s
, '', '', '')
106 # _RandomNameSequence returns no duplicate strings (stochastic)
110 for i
in xrange(TEST_FILES
):
112 self
.nameCheck(s
, '', '', '')
113 self
.assertNotIn(s
, dict)
116 def test_supports_iter(self
):
117 # _RandomNameSequence supports the iterator protocol
127 self
.failOnException("iteration")
129 test_classes
.append(test__RandomNameSequence
)
132 class test__candidate_tempdir_list(TC
):
133 """Test the internal function _candidate_tempdir_list."""
135 def test_nonempty_list(self
):
136 # _candidate_tempdir_list returns a nonempty list of strings
138 cand
= tempfile
._candidate
_tempdir
_list
()
140 self
.assertFalse(len(cand
) == 0)
142 self
.assertIsInstance(c
, basestring
)
144 def test_wanted_dirs(self
):
145 # _candidate_tempdir_list contains the expected directories
147 # Make sure the interesting environment variables are all set.
148 with test_support
.EnvironmentVarGuard() as env
:
149 for envname
in 'TMPDIR', 'TEMP', 'TMP':
150 dirname
= os
.getenv(envname
)
152 env
[envname
] = os
.path
.abspath(envname
)
154 cand
= tempfile
._candidate
_tempdir
_list
()
156 for envname
in 'TMPDIR', 'TEMP', 'TMP':
157 dirname
= os
.getenv(envname
)
158 if not dirname
: raise ValueError
159 self
.assertIn(dirname
, cand
)
162 dirname
= os
.getcwd()
163 except (AttributeError, os
.error
):
166 self
.assertIn(dirname
, cand
)
168 # Not practical to try to verify the presence of OS-specific
169 # paths in this list.
171 test_classes
.append(test__candidate_tempdir_list
)
174 # We test _get_default_tempdir by testing gettempdir.
177 class test__get_candidate_names(TC
):
178 """Test the internal function _get_candidate_names."""
180 def test_retval(self
):
181 # _get_candidate_names returns a _RandomNameSequence object
182 obj
= tempfile
._get
_candidate
_names
()
183 self
.assertIsInstance(obj
, tempfile
._RandomNameSequence
)
185 def test_same_thing(self
):
186 # _get_candidate_names always returns the same object
187 a
= tempfile
._get
_candidate
_names
()
188 b
= tempfile
._get
_candidate
_names
()
190 self
.assertTrue(a
is b
)
192 test_classes
.append(test__get_candidate_names
)
195 class test__mkstemp_inner(TC
):
196 """Test the internal function _mkstemp_inner."""
199 _bflags
= tempfile
._bin
_openflags
200 _tflags
= tempfile
._text
_openflags
204 def __init__(self
, dir, pre
, suf
, bin
):
205 if bin
: flags
= self
._bflags
206 else: flags
= self
._tflags
208 (self
.fd
, self
.name
) = tempfile
._mkstemp
_inner
(dir, pre
, suf
, flags
)
210 def write(self
, str):
211 os
.write(self
.fd
, str)
215 self
._unlink
(self
.name
)
217 def do_create(self
, dir=None, pre
="", suf
="", bin
=1):
219 dir = tempfile
.gettempdir()
221 file = self
.mkstemped(dir, pre
, suf
, bin
)
223 self
.failOnException("_mkstemp_inner")
225 self
.nameCheck(file.name
, dir, pre
, suf
)
228 def test_basic(self
):
229 # _mkstemp_inner can create files
230 self
.do_create().write("blat")
231 self
.do_create(pre
="a").write("blat")
232 self
.do_create(suf
="b").write("blat")
233 self
.do_create(pre
="a", suf
="b").write("blat")
234 self
.do_create(pre
="aa", suf
=".txt").write("blat")
236 def test_basic_many(self
):
237 # _mkstemp_inner can create many files (stochastic)
238 extant
= range(TEST_FILES
)
240 extant
[i
] = self
.do_create(pre
="aa")
242 def test_choose_directory(self
):
243 # _mkstemp_inner can create files in a user-selected directory
244 dir = tempfile
.mkdtemp()
246 self
.do_create(dir=dir).write("blat")
250 def test_file_mode(self
):
251 # _mkstemp_inner creates files with the proper mode
253 return # ugh, can't use SkipTest.
255 file = self
.do_create()
256 mode
= stat
.S_IMODE(os
.stat(file.name
).st_mode
)
258 if sys
.platform
in ('win32', 'os2emx'):
259 # There's no distinction among 'user', 'group' and 'world';
260 # replicate the 'user' bits.
262 expected
= user
* (1 + 8 + 64)
263 self
.assertEqual(mode
, expected
)
265 def test_noinherit(self
):
266 # _mkstemp_inner file handles are not inherited by child processes
268 return # ugh, can't use SkipTest.
270 if test_support
.verbose
:
275 file = self
.do_create()
283 # We have to exec something, so that FD_CLOEXEC will take
284 # effect. The core of this test is therefore in
285 # tf_inherit_check.py, which see.
286 tester
= os
.path
.join(os
.path
.dirname(os
.path
.abspath(me
)),
287 "tf_inherit_check.py")
289 # On Windows a spawn* /path/ with embedded spaces shouldn't be quoted,
290 # but an arg with embedded spaces should be decorated with double
292 if sys
.platform
in ('win32',):
293 decorated
= '"%s"' % sys
.executable
294 tester
= '"%s"' % tester
296 decorated
= sys
.executable
298 retval
= os
.spawnl(os
.P_WAIT
, sys
.executable
, decorated
, tester
, v
, fd
)
299 self
.assertFalse(retval
< 0,
300 "child process caught fatal signal %d" % -retval
)
301 self
.assertFalse(retval
> 0, "child process reports failure %d"%retval
)
303 def test_textmode(self
):
304 # _mkstemp_inner can create files in text mode
306 return # ugh, can't use SkipTest.
308 self
.do_create(bin
=0).write("blat\n")
309 # XXX should test that the file really is a text file
311 test_classes
.append(test__mkstemp_inner
)
314 class test_gettempprefix(TC
):
315 """Test gettempprefix()."""
317 def test_sane_template(self
):
318 # gettempprefix returns a nonempty prefix string
319 p
= tempfile
.gettempprefix()
321 self
.assertIsInstance(p
, basestring
)
322 self
.assertTrue(len(p
) > 0)
324 def test_usable_template(self
):
325 # gettempprefix returns a usable prefix string
327 # Create a temp directory, avoiding use of the prefix.
328 # Then attempt to create a file whose name is
329 # prefix + 'xxxxxx.xxx' in that directory.
330 p
= tempfile
.gettempprefix() + "xxxxxx.xxx"
331 d
= tempfile
.mkdtemp(prefix
="")
333 p
= os
.path
.join(d
, p
)
335 fd
= os
.open(p
, os
.O_RDWR | os
.O_CREAT
)
337 self
.failOnException("os.open")
343 test_classes
.append(test_gettempprefix
)
346 class test_gettempdir(TC
):
347 """Test gettempdir()."""
349 def test_directory_exists(self
):
350 # gettempdir returns a directory which exists
352 dir = tempfile
.gettempdir()
353 self
.assertTrue(os
.path
.isabs(dir) or dir == os
.curdir
,
354 "%s is not an absolute path" % dir)
355 self
.assertTrue(os
.path
.isdir(dir),
356 "%s is not a directory" % dir)
358 def test_directory_writable(self
):
359 # gettempdir returns a directory writable by the user
361 # sneaky: just instantiate a NamedTemporaryFile, which
362 # defaults to writing into the directory returned by
365 file = tempfile
.NamedTemporaryFile()
369 self
.failOnException("create file in %s" % tempfile
.gettempdir())
371 def test_same_thing(self
):
372 # gettempdir always returns the same object
373 a
= tempfile
.gettempdir()
374 b
= tempfile
.gettempdir()
376 self
.assertTrue(a
is b
)
378 test_classes
.append(test_gettempdir
)
381 class test_mkstemp(TC
):
382 """Test mkstemp()."""
384 def do_create(self
, dir=None, pre
="", suf
=""):
386 dir = tempfile
.gettempdir()
388 (fd
, name
) = tempfile
.mkstemp(dir=dir, prefix
=pre
, suffix
=suf
)
389 (ndir
, nbase
) = os
.path
.split(name
)
390 adir
= os
.path
.abspath(dir)
391 self
.assertEqual(adir
, ndir
,
392 "Directory '%s' incorrectly returned as '%s'" % (adir
, ndir
))
394 self
.failOnException("mkstemp")
397 self
.nameCheck(name
, dir, pre
, suf
)
402 def test_basic(self
):
403 # mkstemp can create files
405 self
.do_create(pre
="a")
406 self
.do_create(suf
="b")
407 self
.do_create(pre
="a", suf
="b")
408 self
.do_create(pre
="aa", suf
=".txt")
409 self
.do_create(dir=".")
411 def test_choose_directory(self
):
412 # mkstemp can create directories in a user-selected directory
413 dir = tempfile
.mkdtemp()
415 self
.do_create(dir=dir)
419 test_classes
.append(test_mkstemp
)
422 class test_mkdtemp(TC
):
423 """Test mkdtemp()."""
425 def do_create(self
, dir=None, pre
="", suf
=""):
427 dir = tempfile
.gettempdir()
429 name
= tempfile
.mkdtemp(dir=dir, prefix
=pre
, suffix
=suf
)
431 self
.failOnException("mkdtemp")
434 self
.nameCheck(name
, dir, pre
, suf
)
440 def test_basic(self
):
441 # mkdtemp can create directories
442 os
.rmdir(self
.do_create())
443 os
.rmdir(self
.do_create(pre
="a"))
444 os
.rmdir(self
.do_create(suf
="b"))
445 os
.rmdir(self
.do_create(pre
="a", suf
="b"))
446 os
.rmdir(self
.do_create(pre
="aa", suf
=".txt"))
448 def test_basic_many(self
):
449 # mkdtemp can create many directories (stochastic)
450 extant
= range(TEST_FILES
)
453 extant
[i
] = self
.do_create(pre
="aa")
456 if(isinstance(i
, basestring
)):
459 def test_choose_directory(self
):
460 # mkdtemp can create directories in a user-selected directory
461 dir = tempfile
.mkdtemp()
463 os
.rmdir(self
.do_create(dir=dir))
468 # mkdtemp creates directories with the proper mode
470 return # ugh, can't use SkipTest.
472 dir = self
.do_create()
474 mode
= stat
.S_IMODE(os
.stat(dir).st_mode
)
475 mode
&= 0777 # Mask off sticky bits inherited from /tmp
477 if sys
.platform
in ('win32', 'os2emx'):
478 # There's no distinction among 'user', 'group' and 'world';
479 # replicate the 'user' bits.
481 expected
= user
* (1 + 8 + 64)
482 self
.assertEqual(mode
, expected
)
486 test_classes
.append(test_mkdtemp
)
489 class test_mktemp(TC
):
492 # For safety, all use of mktemp must occur in a private directory.
493 # We must also suppress the RuntimeWarning it generates.
495 self
.dir = tempfile
.mkdtemp()
504 _bflags
= tempfile
._bin
_openflags
506 def __init__(self
, dir, pre
, suf
):
507 self
.name
= tempfile
.mktemp(dir=dir, prefix
=pre
, suffix
=suf
)
508 # Create the file. This will raise an exception if it's
509 # mysteriously appeared in the meanwhile.
510 os
.close(os
.open(self
.name
, self
._bflags
, 0600))
513 self
._unlink
(self
.name
)
515 def do_create(self
, pre
="", suf
=""):
517 file = self
.mktemped(self
.dir, pre
, suf
)
519 self
.failOnException("mktemp")
521 self
.nameCheck(file.name
, self
.dir, pre
, suf
)
524 def test_basic(self
):
525 # mktemp can choose usable file names
527 self
.do_create(pre
="a")
528 self
.do_create(suf
="b")
529 self
.do_create(pre
="a", suf
="b")
530 self
.do_create(pre
="aa", suf
=".txt")
533 # mktemp can choose many usable file names (stochastic)
534 extant
= range(TEST_FILES
)
536 extant
[i
] = self
.do_create(pre
="aa")
538 ## def test_warning(self):
539 ## # mktemp issues a warning when used
540 ## warnings.filterwarnings("error",
541 ## category=RuntimeWarning,
543 ## self.assertRaises(RuntimeWarning,
544 ## tempfile.mktemp, dir=self.dir)
546 test_classes
.append(test_mktemp
)
549 # We test _TemporaryFileWrapper by testing NamedTemporaryFile.
552 class test_NamedTemporaryFile(TC
):
553 """Test NamedTemporaryFile()."""
555 def do_create(self
, dir=None, pre
="", suf
="", delete
=True):
557 dir = tempfile
.gettempdir()
559 file = tempfile
.NamedTemporaryFile(dir=dir, prefix
=pre
, suffix
=suf
,
562 self
.failOnException("NamedTemporaryFile")
564 self
.nameCheck(file.name
, dir, pre
, suf
)
568 def test_basic(self
):
569 # NamedTemporaryFile can create files
571 self
.do_create(pre
="a")
572 self
.do_create(suf
="b")
573 self
.do_create(pre
="a", suf
="b")
574 self
.do_create(pre
="aa", suf
=".txt")
576 def test_creates_named(self
):
577 # NamedTemporaryFile creates files with names
578 f
= tempfile
.NamedTemporaryFile()
579 self
.assertTrue(os
.path
.exists(f
.name
),
580 "NamedTemporaryFile %s does not exist" % f
.name
)
582 def test_del_on_close(self
):
583 # A NamedTemporaryFile is deleted when closed
584 dir = tempfile
.mkdtemp()
586 f
= tempfile
.NamedTemporaryFile(dir=dir)
589 self
.assertFalse(os
.path
.exists(f
.name
),
590 "NamedTemporaryFile %s exists after close" % f
.name
)
594 def test_dis_del_on_close(self
):
595 # Tests that delete-on-close can be disabled
596 dir = tempfile
.mkdtemp()
599 f
= tempfile
.NamedTemporaryFile(dir=dir, delete
=False)
603 self
.assertTrue(os
.path
.exists(f
.name
),
604 "NamedTemporaryFile %s missing after close" % f
.name
)
610 def test_multiple_close(self
):
611 # A NamedTemporaryFile can be closed many times without error
612 f
= tempfile
.NamedTemporaryFile()
619 self
.failOnException("close")
621 def test_context_manager(self
):
622 # A NamedTemporaryFile can be used as a context manager
623 with tempfile
.NamedTemporaryFile() as f
:
624 self
.assertTrue(os
.path
.exists(f
.name
))
625 self
.assertFalse(os
.path
.exists(f
.name
))
629 self
.assertRaises(ValueError, use_closed
)
631 # How to test the mode and bufsize parameters?
633 test_classes
.append(test_NamedTemporaryFile
)
635 class test_SpooledTemporaryFile(TC
):
636 """Test SpooledTemporaryFile()."""
638 def do_create(self
, max_size
=0, dir=None, pre
="", suf
=""):
640 dir = tempfile
.gettempdir()
642 file = tempfile
.SpooledTemporaryFile(max_size
=max_size
, dir=dir, prefix
=pre
, suffix
=suf
)
644 self
.failOnException("SpooledTemporaryFile")
649 def test_basic(self
):
650 # SpooledTemporaryFile can create files
652 self
.assertFalse(f
._rolled
)
653 f
= self
.do_create(max_size
=100, pre
="a", suf
=".txt")
654 self
.assertFalse(f
._rolled
)
656 def test_del_on_close(self
):
657 # A SpooledTemporaryFile is deleted when closed
658 dir = tempfile
.mkdtemp()
660 f
= tempfile
.SpooledTemporaryFile(max_size
=10, dir=dir)
661 self
.assertFalse(f
._rolled
)
663 self
.assertTrue(f
._rolled
)
666 self
.assertFalse(os
.path
.exists(filename
),
667 "SpooledTemporaryFile %s exists after close" % filename
)
671 def test_rewrite_small(self
):
672 # A SpooledTemporaryFile can be written to multiple within the max_size
673 f
= self
.do_create(max_size
=30)
674 self
.assertFalse(f
._rolled
)
678 self
.assertFalse(f
._rolled
)
680 def test_write_sequential(self
):
681 # A SpooledTemporaryFile should hold exactly max_size bytes, and roll
683 f
= self
.do_create(max_size
=30)
684 self
.assertFalse(f
._rolled
)
686 self
.assertFalse(f
._rolled
)
688 self
.assertFalse(f
._rolled
)
690 self
.assertTrue(f
._rolled
)
692 def test_sparse(self
):
693 # A SpooledTemporaryFile that is written late in the file will extend
695 f
= self
.do_create(max_size
=30)
696 self
.assertFalse(f
._rolled
)
698 self
.assertFalse(f
._rolled
)
700 self
.assertTrue(f
._rolled
)
702 def test_fileno(self
):
703 # A SpooledTemporaryFile should roll over to a real file on fileno()
704 f
= self
.do_create(max_size
=30)
705 self
.assertFalse(f
._rolled
)
706 self
.assertTrue(f
.fileno() > 0)
707 self
.assertTrue(f
._rolled
)
709 def test_multiple_close_before_rollover(self
):
710 # A SpooledTemporaryFile can be closed many times without error
711 f
= tempfile
.SpooledTemporaryFile()
713 self
.assertFalse(f
._rolled
)
719 self
.failOnException("close")
721 def test_multiple_close_after_rollover(self
):
722 # A SpooledTemporaryFile can be closed many times without error
723 f
= tempfile
.SpooledTemporaryFile(max_size
=1)
725 self
.assertTrue(f
._rolled
)
731 self
.failOnException("close")
733 def test_bound_methods(self
):
734 # It should be OK to steal a bound method from a SpooledTemporaryFile
735 # and use it independently; when the file rolls over, those bound
736 # methods should continue to function
737 f
= self
.do_create(max_size
=30)
745 self
.assertTrue(read(70) == 'a'*35 + 'b'*35)
747 def test_context_manager_before_rollover(self
):
748 # A SpooledTemporaryFile can be used as a context manager
749 with tempfile
.SpooledTemporaryFile(max_size
=1) as f
:
750 self
.assertFalse(f
._rolled
)
751 self
.assertFalse(f
.closed
)
752 self
.assertTrue(f
.closed
)
756 self
.assertRaises(ValueError, use_closed
)
758 def test_context_manager_during_rollover(self
):
759 # A SpooledTemporaryFile can be used as a context manager
760 with tempfile
.SpooledTemporaryFile(max_size
=1) as f
:
761 self
.assertFalse(f
._rolled
)
764 self
.assertTrue(f
._rolled
)
765 self
.assertFalse(f
.closed
)
766 self
.assertTrue(f
.closed
)
770 self
.assertRaises(ValueError, use_closed
)
772 def test_context_manager_after_rollover(self
):
773 # A SpooledTemporaryFile can be used as a context manager
774 f
= tempfile
.SpooledTemporaryFile(max_size
=1)
777 self
.assertTrue(f
._rolled
)
779 self
.assertFalse(f
.closed
)
780 self
.assertTrue(f
.closed
)
784 self
.assertRaises(ValueError, use_closed
)
787 test_classes
.append(test_SpooledTemporaryFile
)
790 class test_TemporaryFile(TC
):
791 """Test TemporaryFile()."""
793 def test_basic(self
):
794 # TemporaryFile can create files
795 # No point in testing the name params - the file has no name.
797 tempfile
.TemporaryFile()
799 self
.failOnException("TemporaryFile")
801 def test_has_no_name(self
):
802 # TemporaryFile creates files with no names (on this system)
803 dir = tempfile
.mkdtemp()
804 f
= tempfile
.TemporaryFile(dir=dir)
807 # Sneaky: because this file has no name, it should not prevent
808 # us from removing the directory it was created in.
816 self
.failOnException("rmdir", ei
)
818 def test_multiple_close(self
):
819 # A TemporaryFile can be closed many times without error
820 f
= tempfile
.TemporaryFile()
827 self
.failOnException("close")
829 # How to test the mode and bufsize parameters?
832 if tempfile
.NamedTemporaryFile
is not tempfile
.TemporaryFile
:
833 test_classes
.append(test_TemporaryFile
)
836 test_support
.run_unittest(*test_classes
)
838 if __name__
== "__main__":