1 # tempfile.py unit tests. 2 import tempfile 3 import errno 4 import io 5 import os 6 import signal 7 import shutil 8 import sys 9 import re 10 import warnings 11 12 import unittest 13 from test import test_support as support 14 15 warnings.filterwarnings("ignore", 16 category=RuntimeWarning, 17 message="mktemp", module=__name__) 18 19 if hasattr(os, 'stat'): 20 import stat 21 has_stat = 1 22 else: 23 has_stat = 0 24 25 has_textmode = (tempfile._text_openflags != tempfile._bin_openflags) 26 has_spawnl = hasattr(os, 'spawnl') 27 28 # TEST_FILES may need to be tweaked for systems depending on the maximum 29 # number of files that can be opened at one time (see ulimit -n) 30 if sys.platform in ('openbsd3', 'openbsd4'): 31 TEST_FILES = 48 32 else: 33 TEST_FILES = 100 34 35 # This is organized as one test for each chunk of code in tempfile.py, 36 # in order of their appearance in the file. Testing which requires 37 # threads is not done here. 38 39 # Common functionality. 40 class TC(unittest.TestCase): 41 42 str_check = re.compile(r"[a-zA-Z0-9_-]{6}$") 43 44 def failOnException(self, what, ei=None): 45 if ei is None: 46 ei = sys.exc_info() 47 self.fail("%s raised %s: %s" % (what, ei[0], ei[1])) 48 49 def nameCheck(self, name, dir, pre, suf): 50 (ndir, nbase) = os.path.split(name) 51 npre = nbase[:len(pre)] 52 nsuf = nbase[len(nbase)-len(suf):] 53 54 # check for equality of the absolute paths! 55 self.assertEqual(os.path.abspath(ndir), os.path.abspath(dir), 56 "file '%s' not in directory '%s'" % (name, dir)) 57 self.assertEqual(npre, pre, 58 "file '%s' does not begin with '%s'" % (nbase, pre)) 59 self.assertEqual(nsuf, suf, 60 "file '%s' does not end with '%s'" % (nbase, suf)) 61 62 nbase = nbase[len(pre):len(nbase)-len(suf)] 63 self.assertTrue(self.str_check.match(nbase), 64 "random string '%s' does not match /^[a-zA-Z0-9_-]{6}$/" 65 % nbase) 66 67 test_classes = [] 68 69 class test_exports(TC): 70 def test_exports(self): 71 # There are no surprising symbols in the tempfile module 72 dict = tempfile.__dict__ 73 74 expected = { 75 "NamedTemporaryFile" : 1, 76 "TemporaryFile" : 1, 77 "mkstemp" : 1, 78 "mkdtemp" : 1, 79 "mktemp" : 1, 80 "TMP_MAX" : 1, 81 "gettempprefix" : 1, 82 "gettempdir" : 1, 83 "tempdir" : 1, 84 "template" : 1, 85 "SpooledTemporaryFile" : 1 86 } 87 88 unexp = [] 89 for key in dict: 90 if key[0] != '_' and key not in expected: 91 unexp.append(key) 92 self.assertTrue(len(unexp) == 0, 93 "unexpected keys: %s" % unexp) 94 95 test_classes.append(test_exports) 96 97 98 class test__RandomNameSequence(TC): 99 """Test the internal iterator object _RandomNameSequence.""" 100 101 def setUp(self): 102 self.r = tempfile._RandomNameSequence() 103 104 def test_get_six_char_str(self): 105 # _RandomNameSequence returns a six-character string 106 s = self.r.next() 107 self.nameCheck(s, '', '', '') 108 109 def test_many(self): 110 # _RandomNameSequence returns no duplicate strings (stochastic) 111 112 dict = {} 113 r = self.r 114 for i in xrange(TEST_FILES): 115 s = r.next() 116 self.nameCheck(s, '', '', '') 117 self.assertNotIn(s, dict) 118 dict[s] = 1 119 120 def test_supports_iter(self): 121 # _RandomNameSequence supports the iterator protocol 122 123 i = 0 124 r = self.r 125 try: 126 for s in r: 127 i += 1 128 if i == 20: 129 break 130 except: 131 self.failOnException("iteration") 132 133 @unittest.skipUnless(hasattr(os, 'fork'), 134 "os.fork is required for this test") 135 def test_process_awareness(self): 136 # ensure that the random source differs between 137 # child and parent. 138 read_fd, write_fd = os.pipe() 139 pid = None 140 try: 141 pid = os.fork() 142 if not pid: 143 os.close(read_fd) 144 os.write(write_fd, next(self.r).encode("ascii")) 145 os.close(write_fd) 146 # bypass the normal exit handlers- leave those to 147 # the parent. 148 os._exit(0) 149 parent_value = next(self.r) 150 child_value = os.read(read_fd, len(parent_value)).decode("ascii") 151 finally: 152 if pid: 153 # best effort to ensure the process can't bleed out 154 # via any bugs above 155 try: 156 os.kill(pid, signal.SIGKILL) 157 except EnvironmentError: 158 pass 159 os.close(read_fd) 160 os.close(write_fd) 161 self.assertNotEqual(child_value, parent_value) 162 163 164 test_classes.append(test__RandomNameSequence) 165 166 167 class test__candidate_tempdir_list(TC): 168 """Test the internal function _candidate_tempdir_list.""" 169 170 def test_nonempty_list(self): 171 # _candidate_tempdir_list returns a nonempty list of strings 172 173 cand = tempfile._candidate_tempdir_list() 174 175 self.assertFalse(len(cand) == 0) 176 for c in cand: 177 self.assertIsInstance(c, basestring) 178 179 def test_wanted_dirs(self): 180 # _candidate_tempdir_list contains the expected directories 181 182 # Make sure the interesting environment variables are all set. 183 with support.EnvironmentVarGuard() as env: 184 for envname in 'TMPDIR', 'TEMP', 'TMP': 185 dirname = os.getenv(envname) 186 if not dirname: 187 env[envname] = os.path.abspath(envname) 188 189 cand = tempfile._candidate_tempdir_list() 190 191 for envname in 'TMPDIR', 'TEMP', 'TMP': 192 dirname = os.getenv(envname) 193 if not dirname: raise ValueError 194 self.assertIn(dirname, cand) 195 196 try: 197 dirname = os.getcwd() 198 except (AttributeError, os.error): 199 dirname = os.curdir 200 201 self.assertIn(dirname, cand) 202 203 # Not practical to try to verify the presence of OS-specific 204 # paths in this list. 205 206 test_classes.append(test__candidate_tempdir_list) 207 208 # We test _get_default_tempdir some more by testing gettempdir. 209 210 class TestGetDefaultTempdir(TC): 211 """Test _get_default_tempdir().""" 212 213 def test_no_files_left_behind(self): 214 # use a private empty directory 215 our_temp_directory = tempfile.mkdtemp() 216 try: 217 # force _get_default_tempdir() to consider our empty directory 218 def our_candidate_list(): 219 return [our_temp_directory] 220 221 with support.swap_attr(tempfile, "_candidate_tempdir_list", 222 our_candidate_list): 223 # verify our directory is empty after _get_default_tempdir() 224 tempfile._get_default_tempdir() 225 self.assertEqual(os.listdir(our_temp_directory), []) 226 227 def raise_OSError(*args, **kwargs): 228 raise OSError(-1) 229 230 with support.swap_attr(io, "open", raise_OSError): 231 # test again with failing io.open() 232 with self.assertRaises(IOError) as cm: 233 tempfile._get_default_tempdir() 234 self.assertEqual(cm.exception.errno, errno.ENOENT) 235 self.assertEqual(os.listdir(our_temp_directory), []) 236 237 open = io.open 238 def bad_writer(*args, **kwargs): 239 fp = open(*args, **kwargs) 240 fp.write = raise_OSError 241 return fp 242 243 with support.swap_attr(io, "open", bad_writer): 244 # test again with failing write() 245 with self.assertRaises(IOError) as cm: 246 tempfile._get_default_tempdir() 247 self.assertEqual(cm.exception.errno, errno.ENOENT) 248 self.assertEqual(os.listdir(our_temp_directory), []) 249 finally: 250 shutil.rmtree(our_temp_directory) 251 252 test_classes.append(TestGetDefaultTempdir) 253 254 255 class test__get_candidate_names(TC): 256 """Test the internal function _get_candidate_names.""" 257 258 def test_retval(self): 259 # _get_candidate_names returns a _RandomNameSequence object 260 obj = tempfile._get_candidate_names() 261 self.assertIsInstance(obj, tempfile._RandomNameSequence) 262 263 def test_same_thing(self): 264 # _get_candidate_names always returns the same object 265 a = tempfile._get_candidate_names() 266 b = tempfile._get_candidate_names() 267 268 self.assertTrue(a is b) 269 270 test_classes.append(test__get_candidate_names) 271 272 273 class test__mkstemp_inner(TC): 274 """Test the internal function _mkstemp_inner.""" 275 276 class mkstemped: 277 _bflags = tempfile._bin_openflags 278 _tflags = tempfile._text_openflags 279 _close = os.close 280 _unlink = os.unlink 281 282 def __init__(self, dir, pre, suf, bin): 283 if bin: flags = self._bflags 284 else: flags = self._tflags 285 286 (self.fd, self.name) = tempfile._mkstemp_inner(dir, pre, suf, flags) 287 288 def write(self, str): 289 os.write(self.fd, str) 290 291 def __del__(self): 292 self._close(self.fd) 293 self._unlink(self.name) 294 295 def do_create(self, dir=None, pre="", suf="", bin=1): 296 if dir is None: 297 dir = tempfile.gettempdir() 298 try: 299 file = self.mkstemped(dir, pre, suf, bin) 300 except: 301 self.failOnException("_mkstemp_inner") 302 303 self.nameCheck(file.name, dir, pre, suf) 304 return file 305 306 def test_basic(self): 307 # _mkstemp_inner can create files 308 self.do_create().write("blat") 309 self.do_create(pre="a").write("blat") 310 self.do_create(suf="b").write("blat") 311 self.do_create(pre="a", suf="b").write("blat") 312 self.do_create(pre="aa", suf=".txt").write("blat") 313 314 def test_basic_many(self): 315 # _mkstemp_inner can create many files (stochastic) 316 extant = range(TEST_FILES) 317 for i in extant: 318 extant[i] = self.do_create(pre="aa") 319 320 def test_choose_directory(self): 321 # _mkstemp_inner can create files in a user-selected directory 322 dir = tempfile.mkdtemp() 323 try: 324 self.do_create(dir=dir).write("blat") 325 finally: 326 os.rmdir(dir) 327 328 def test_file_mode(self): 329 # _mkstemp_inner creates files with the proper mode 330 if not has_stat: 331 return # ugh, can't use SkipTest. 332 333 file = self.do_create() 334 mode = stat.S_IMODE(os.stat(file.name).st_mode) 335 expected = 0600 336 if sys.platform in ('win32', 'os2emx'): 337 # There's no distinction among 'user', 'group' and 'world'; 338 # replicate the 'user' bits. 339 user = expected >> 6 340 expected = user * (1 + 8 + 64) 341 self.assertEqual(mode, expected) 342 343 def test_noinherit(self): 344 # _mkstemp_inner file handles are not inherited by child processes 345 if not has_spawnl: 346 return # ugh, can't use SkipTest. 347 348 if support.verbose: 349 v="v" 350 else: 351 v="q" 352 353 file = self.do_create() 354 fd = "%d" % file.fd 355 356 try: 357 me = __file__ 358 except NameError: 359 me = sys.argv[0] 360 361 # We have to exec something, so that FD_CLOEXEC will take 362 # effect. The core of this test is therefore in 363 # tf_inherit_check.py, which see. 364 tester = os.path.join(os.path.dirname(os.path.abspath(me)), 365 "tf_inherit_check.py") 366 367 # On Windows a spawn* /path/ with embedded spaces shouldn't be quoted, 368 # but an arg with embedded spaces should be decorated with double 369 # quotes on each end 370 if sys.platform in ('win32',): 371 decorated = '"%s"' % sys.executable 372 tester = '"%s"' % tester 373 else: 374 decorated = sys.executable 375 376 retval = os.spawnl(os.P_WAIT, sys.executable, decorated, tester, v, fd) 377 self.assertFalse(retval < 0, 378 "child process caught fatal signal %d" % -retval) 379 self.assertFalse(retval > 0, "child process reports failure %d"%retval) 380 381 def test_textmode(self): 382 # _mkstemp_inner can create files in text mode 383 if not has_textmode: 384 return # ugh, can't use SkipTest. 385 386 self.do_create(bin=0).write("blat\n") 387 # XXX should test that the file really is a text file 388 389 test_classes.append(test__mkstemp_inner) 390 391 392 class test_gettempprefix(TC): 393 """Test gettempprefix().""" 394 395 def test_sane_template(self): 396 # gettempprefix returns a nonempty prefix string 397 p = tempfile.gettempprefix() 398 399 self.assertIsInstance(p, basestring) 400 self.assertTrue(len(p) > 0) 401 402 def test_usable_template(self): 403 # gettempprefix returns a usable prefix string 404 405 # Create a temp directory, avoiding use of the prefix. 406 # Then attempt to create a file whose name is 407 # prefix + 'xxxxxx.xxx' in that directory. 408 p = tempfile.gettempprefix() + "xxxxxx.xxx" 409 d = tempfile.mkdtemp(prefix="") 410 try: 411 p = os.path.join(d, p) 412 try: 413 fd = os.open(p, os.O_RDWR | os.O_CREAT) 414 except: 415 self.failOnException("os.open") 416 os.close(fd) 417 os.unlink(p) 418 finally: 419 os.rmdir(d) 420 421 test_classes.append(test_gettempprefix) 422 423 424 class test_gettempdir(TC): 425 """Test gettempdir().""" 426 427 def test_directory_exists(self): 428 # gettempdir returns a directory which exists 429 430 dir = tempfile.gettempdir() 431 self.assertTrue(os.path.isabs(dir) or dir == os.curdir, 432 "%s is not an absolute path" % dir) 433 self.assertTrue(os.path.isdir(dir), 434 "%s is not a directory" % dir) 435 436 def test_directory_writable(self): 437 # gettempdir returns a directory writable by the user 438 439 # sneaky: just instantiate a NamedTemporaryFile, which 440 # defaults to writing into the directory returned by 441 # gettempdir. 442 try: 443 file = tempfile.NamedTemporaryFile() 444 file.write("blat") 445 file.close() 446 except: 447 self.failOnException("create file in %s" % tempfile.gettempdir()) 448 449 def test_same_thing(self): 450 # gettempdir always returns the same object 451 a = tempfile.gettempdir() 452 b = tempfile.gettempdir() 453 454 self.assertTrue(a is b) 455 456 test_classes.append(test_gettempdir) 457 458 459 class test_mkstemp(TC): 460 """Test mkstemp().""" 461 462 def do_create(self, dir=None, pre="", suf=""): 463 if dir is None: 464 dir = tempfile.gettempdir() 465 try: 466 (fd, name) = tempfile.mkstemp(dir=dir, prefix=pre, suffix=suf) 467 (ndir, nbase) = os.path.split(name) 468 adir = os.path.abspath(dir) 469 self.assertEqual(adir, ndir, 470 "Directory '%s' incorrectly returned as '%s'" % (adir, ndir)) 471 except: 472 self.failOnException("mkstemp") 473 474 try: 475 self.nameCheck(name, dir, pre, suf) 476 finally: 477 os.close(fd) 478 os.unlink(name) 479 480 def test_basic(self): 481 # mkstemp can create files 482 self.do_create() 483 self.do_create(pre="a") 484 self.do_create(suf="b") 485 self.do_create(pre="a", suf="b") 486 self.do_create(pre="aa", suf=".txt") 487 self.do_create(dir=".") 488 489 def test_choose_directory(self): 490 # mkstemp can create directories in a user-selected directory 491 dir = tempfile.mkdtemp() 492 try: 493 self.do_create(dir=dir) 494 finally: 495 os.rmdir(dir) 496 497 test_classes.append(test_mkstemp) 498 499 500 class test_mkdtemp(TC): 501 """Test mkdtemp().""" 502 503 def do_create(self, dir=None, pre="", suf=""): 504 if dir is None: 505 dir = tempfile.gettempdir() 506 try: 507 name = tempfile.mkdtemp(dir=dir, prefix=pre, suffix=suf) 508 except: 509 self.failOnException("mkdtemp") 510 511 try: 512 self.nameCheck(name, dir, pre, suf) 513 return name 514 except: 515 os.rmdir(name) 516 raise 517 518 def test_basic(self): 519 # mkdtemp can create directories 520 os.rmdir(self.do_create()) 521 os.rmdir(self.do_create(pre="a")) 522 os.rmdir(self.do_create(suf="b")) 523 os.rmdir(self.do_create(pre="a", suf="b")) 524 os.rmdir(self.do_create(pre="aa", suf=".txt")) 525 526 def test_basic_many(self): 527 # mkdtemp can create many directories (stochastic) 528 extant = range(TEST_FILES) 529 try: 530 for i in extant: 531 extant[i] = self.do_create(pre="aa") 532 finally: 533 for i in extant: 534 if(isinstance(i, basestring)): 535 os.rmdir(i) 536 537 def test_choose_directory(self): 538 # mkdtemp can create directories in a user-selected directory 539 dir = tempfile.mkdtemp() 540 try: 541 os.rmdir(self.do_create(dir=dir)) 542 finally: 543 os.rmdir(dir) 544 545 def test_mode(self): 546 # mkdtemp creates directories with the proper mode 547 if not has_stat: 548 return # ugh, can't use SkipTest. 549 550 dir = self.do_create() 551 try: 552 mode = stat.S_IMODE(os.stat(dir).st_mode) 553 mode &= 0777 # Mask off sticky bits inherited from /tmp 554 expected = 0700 555 if sys.platform in ('win32', 'os2emx'): 556 # There's no distinction among 'user', 'group' and 'world'; 557 # replicate the 'user' bits. 558 user = expected >> 6 559 expected = user * (1 + 8 + 64) 560 self.assertEqual(mode, expected) 561 finally: 562 os.rmdir(dir) 563 564 test_classes.append(test_mkdtemp) 565 566 567 class test_mktemp(TC): 568 """Test mktemp().""" 569 570 # For safety, all use of mktemp must occur in a private directory. 571 # We must also suppress the RuntimeWarning it generates. 572 def setUp(self): 573 self.dir = tempfile.mkdtemp() 574 575 def tearDown(self): 576 if self.dir: 577 os.rmdir(self.dir) 578 self.dir = None 579 580 class mktemped: 581 _unlink = os.unlink 582 _bflags = tempfile._bin_openflags 583 584 def __init__(self, dir, pre, suf): 585 self.name = tempfile.mktemp(dir=dir, prefix=pre, suffix=suf) 586 # Create the file. This will raise an exception if it's 587 # mysteriously appeared in the meanwhile. 588 os.close(os.open(self.name, self._bflags, 0600)) 589 590 def __del__(self): 591 self._unlink(self.name) 592 593 def do_create(self, pre="", suf=""): 594 try: 595 file = self.mktemped(self.dir, pre, suf) 596 except: 597 self.failOnException("mktemp") 598 599 self.nameCheck(file.name, self.dir, pre, suf) 600 return file 601 602 def test_basic(self): 603 # mktemp can choose usable file names 604 self.do_create() 605 self.do_create(pre="a") 606 self.do_create(suf="b") 607 self.do_create(pre="a", suf="b") 608 self.do_create(pre="aa", suf=".txt") 609 610 def test_many(self): 611 # mktemp can choose many usable file names (stochastic) 612 extant = range(TEST_FILES) 613 for i in extant: 614 extant[i] = self.do_create(pre="aa") 615 616 ## def test_warning(self): 617 ## # mktemp issues a warning when used 618 ## warnings.filterwarnings("error", 619 ## category=RuntimeWarning, 620 ## message="mktemp") 621 ## self.assertRaises(RuntimeWarning, 622 ## tempfile.mktemp, dir=self.dir) 623 624 test_classes.append(test_mktemp) 625 626 627 # We test _TemporaryFileWrapper by testing NamedTemporaryFile. 628 629 630 class test_NamedTemporaryFile(TC): 631 """Test NamedTemporaryFile().""" 632 633 def do_create(self, dir=None, pre="", suf="", delete=True): 634 if dir is None: 635 dir = tempfile.gettempdir() 636 try: 637 file = tempfile.NamedTemporaryFile(dir=dir, prefix=pre, suffix=suf, 638 delete=delete) 639 except: 640 self.failOnException("NamedTemporaryFile") 641 642 self.nameCheck(file.name, dir, pre, suf) 643 return file 644 645 646 def test_basic(self): 647 # NamedTemporaryFile can create files 648 self.do_create() 649 self.do_create(pre="a") 650 self.do_create(suf="b") 651 self.do_create(pre="a", suf="b") 652 self.do_create(pre="aa", suf=".txt") 653 654 def test_creates_named(self): 655 # NamedTemporaryFile creates files with names 656 f = tempfile.NamedTemporaryFile() 657 self.assertTrue(os.path.exists(f.name), 658 "NamedTemporaryFile %s does not exist" % f.name) 659 660 def test_del_on_close(self): 661 # A NamedTemporaryFile is deleted when closed 662 dir = tempfile.mkdtemp() 663 try: 664 f = tempfile.NamedTemporaryFile(dir=dir) 665 f.write('blat') 666 f.close() 667 self.assertFalse(os.path.exists(f.name), 668 "NamedTemporaryFile %s exists after close" % f.name) 669 finally: 670 os.rmdir(dir) 671 672 def test_dis_del_on_close(self): 673 # Tests that delete-on-close can be disabled 674 dir = tempfile.mkdtemp() 675 tmp = None 676 try: 677 f = tempfile.NamedTemporaryFile(dir=dir, delete=False) 678 tmp = f.name 679 f.write('blat') 680 f.close() 681 self.assertTrue(os.path.exists(f.name), 682 "NamedTemporaryFile %s missing after close" % f.name) 683 finally: 684 if tmp is not None: 685 os.unlink(tmp) 686 os.rmdir(dir) 687 688 def test_multiple_close(self): 689 # A NamedTemporaryFile can be closed many times without error 690 f = tempfile.NamedTemporaryFile() 691 f.write('abc\n') 692 f.close() 693 try: 694 f.close() 695 f.close() 696 except: 697 self.failOnException("close") 698 699 def test_context_manager(self): 700 # A NamedTemporaryFile can be used as a context manager 701 with tempfile.NamedTemporaryFile() as f: 702 self.assertTrue(os.path.exists(f.name)) 703 self.assertFalse(os.path.exists(f.name)) 704 def use_closed(): 705 with f: 706 pass 707 self.assertRaises(ValueError, use_closed) 708 709 # How to test the mode and bufsize parameters? 710 711 test_classes.append(test_NamedTemporaryFile) 712 713 class test_SpooledTemporaryFile(TC): 714 """Test SpooledTemporaryFile().""" 715 716 def do_create(self, max_size=0, dir=None, pre="", suf=""): 717 if dir is None: 718 dir = tempfile.gettempdir() 719 try: 720 file = tempfile.SpooledTemporaryFile(max_size=max_size, dir=dir, prefix=pre, suffix=suf) 721 except: 722 self.failOnException("SpooledTemporaryFile") 723 724 return file 725 726 727 def test_basic(self): 728 # SpooledTemporaryFile can create files 729 f = self.do_create() 730 self.assertFalse(f._rolled) 731 f = self.do_create(max_size=100, pre="a", suf=".txt") 732 self.assertFalse(f._rolled) 733 734 def test_del_on_close(self): 735 # A SpooledTemporaryFile is deleted when closed 736 dir = tempfile.mkdtemp() 737 try: 738 f = tempfile.SpooledTemporaryFile(max_size=10, dir=dir) 739 self.assertFalse(f._rolled) 740 f.write('blat ' * 5) 741 self.assertTrue(f._rolled) 742 filename = f.name 743 f.close() 744 self.assertFalse(os.path.exists(filename), 745 "SpooledTemporaryFile %s exists after close" % filename) 746 finally: 747 os.rmdir(dir) 748 749 def test_rewrite_small(self): 750 # A SpooledTemporaryFile can be written to multiple within the max_size 751 f = self.do_create(max_size=30) 752 self.assertFalse(f._rolled) 753 for i in range(5): 754 f.seek(0, 0) 755 f.write('x' * 20) 756 self.assertFalse(f._rolled) 757 758 def test_write_sequential(self): 759 # A SpooledTemporaryFile should hold exactly max_size bytes, and roll 760 # over afterward 761 f = self.do_create(max_size=30) 762 self.assertFalse(f._rolled) 763 f.write('x' * 20) 764 self.assertFalse(f._rolled) 765 f.write('x' * 10) 766 self.assertFalse(f._rolled) 767 f.write('x') 768 self.assertTrue(f._rolled) 769 770 def test_writelines(self): 771 # Verify writelines with a SpooledTemporaryFile 772 f = self.do_create() 773 f.writelines((b'x', b'y', b'z')) 774 f.seek(0) 775 buf = f.read() 776 self.assertEqual(buf, b'xyz') 777 778 def test_writelines_sequential(self): 779 # A SpooledTemporaryFile should hold exactly max_size bytes, and roll 780 # over afterward 781 f = self.do_create(max_size=35) 782 f.writelines((b'x' * 20, b'x' * 10, b'x' * 5)) 783 self.assertFalse(f._rolled) 784 f.write(b'x') 785 self.assertTrue(f._rolled) 786 787 def test_xreadlines(self): 788 f = self.do_create(max_size=20) 789 f.write(b'abc\n' * 5) 790 f.seek(0) 791 self.assertFalse(f._rolled) 792 self.assertEqual(list(f.xreadlines()), [b'abc\n'] * 5) 793 f.write(b'x\ny') 794 self.assertTrue(f._rolled) 795 f.seek(0) 796 self.assertEqual(list(f.xreadlines()), [b'abc\n'] * 5 + [b'x\n', b'y']) 797 798 def test_sparse(self): 799 # A SpooledTemporaryFile that is written late in the file will extend 800 # when that occurs 801 f = self.do_create(max_size=30) 802 self.assertFalse(f._rolled) 803 f.seek(100, 0) 804 self.assertFalse(f._rolled) 805 f.write('x') 806 self.assertTrue(f._rolled) 807 808 def test_fileno(self): 809 # A SpooledTemporaryFile should roll over to a real file on fileno() 810 f = self.do_create(max_size=30) 811 self.assertFalse(f._rolled) 812 self.assertTrue(f.fileno() > 0) 813 self.assertTrue(f._rolled) 814 815 def test_multiple_close_before_rollover(self): 816 # A SpooledTemporaryFile can be closed many times without error 817 f = tempfile.SpooledTemporaryFile() 818 f.write('abc\n') 819 self.assertFalse(f._rolled) 820 f.close() 821 try: 822 f.close() 823 f.close() 824 except: 825 self.failOnException("close") 826 827 def test_multiple_close_after_rollover(self): 828 # A SpooledTemporaryFile can be closed many times without error 829 f = tempfile.SpooledTemporaryFile(max_size=1) 830 f.write('abc\n') 831 self.assertTrue(f._rolled) 832 f.close() 833 try: 834 f.close() 835 f.close() 836 except: 837 self.failOnException("close") 838 839 def test_bound_methods(self): 840 # It should be OK to steal a bound method from a SpooledTemporaryFile 841 # and use it independently; when the file rolls over, those bound 842 # methods should continue to function 843 f = self.do_create(max_size=30) 844 read = f.read 845 write = f.write 846 seek = f.seek 847 848 write("a" * 35) 849 write("b" * 35) 850 seek(0, 0) 851 self.assertTrue(read(70) == 'a'*35 + 'b'*35) 852 853 def test_properties(self): 854 f = tempfile.SpooledTemporaryFile(max_size=10) 855 f.write(b'x' * 10) 856 self.assertFalse(f._rolled) 857 self.assertEqual(f.mode, 'w+b') 858 self.assertIsNone(f.name) 859 with self.assertRaises(AttributeError): 860 f.newlines 861 with self.assertRaises(AttributeError): 862 f.encoding 863 864 f.write(b'x') 865 self.assertTrue(f._rolled) 866 self.assertEqual(f.mode, 'w+b') 867 self.assertIsNotNone(f.name) 868 with self.assertRaises(AttributeError): 869 f.newlines 870 with self.assertRaises(AttributeError): 871 f.encoding 872 873 def test_context_manager_before_rollover(self): 874 # A SpooledTemporaryFile can be used as a context manager 875 with tempfile.SpooledTemporaryFile(max_size=1) as f: 876 self.assertFalse(f._rolled) 877 self.assertFalse(f.closed) 878 self.assertTrue(f.closed) 879 def use_closed(): 880 with f: 881 pass 882 self.assertRaises(ValueError, use_closed) 883 884 def test_context_manager_during_rollover(self): 885 # A SpooledTemporaryFile can be used as a context manager 886 with tempfile.SpooledTemporaryFile(max_size=1) as f: 887 self.assertFalse(f._rolled) 888 f.write('abc\n') 889 f.flush() 890 self.assertTrue(f._rolled) 891 self.assertFalse(f.closed) 892 self.assertTrue(f.closed) 893 def use_closed(): 894 with f: 895 pass 896 self.assertRaises(ValueError, use_closed) 897 898 def test_context_manager_after_rollover(self): 899 # A SpooledTemporaryFile can be used as a context manager 900 f = tempfile.SpooledTemporaryFile(max_size=1) 901 f.write('abc\n') 902 f.flush() 903 self.assertTrue(f._rolled) 904 with f: 905 self.assertFalse(f.closed) 906 self.assertTrue(f.closed) 907 def use_closed(): 908 with f: 909 pass 910 self.assertRaises(ValueError, use_closed) 911 912 913 test_classes.append(test_SpooledTemporaryFile) 914 915 916 class test_TemporaryFile(TC): 917 """Test TemporaryFile().""" 918 919 def test_basic(self): 920 # TemporaryFile can create files 921 # No point in testing the name params - the file has no name. 922 try: 923 tempfile.TemporaryFile() 924 except: 925 self.failOnException("TemporaryFile") 926 927 def test_has_no_name(self): 928 # TemporaryFile creates files with no names (on this system) 929 dir = tempfile.mkdtemp() 930 f = tempfile.TemporaryFile(dir=dir) 931 f.write('blat') 932 933 # Sneaky: because this file has no name, it should not prevent 934 # us from removing the directory it was created in. 935 try: 936 os.rmdir(dir) 937 except: 938 ei = sys.exc_info() 939 # cleanup 940 f.close() 941 os.rmdir(dir) 942 self.failOnException("rmdir", ei) 943 944 def test_multiple_close(self): 945 # A TemporaryFile can be closed many times without error 946 f = tempfile.TemporaryFile() 947 f.write('abc\n') 948 f.close() 949 try: 950 f.close() 951 f.close() 952 except: 953 self.failOnException("close") 954 955 # How to test the mode and bufsize parameters? 956 957 958 if tempfile.NamedTemporaryFile is not tempfile.TemporaryFile: 959 test_classes.append(test_TemporaryFile) 960 961 def test_main(): 962 support.run_unittest(*test_classes) 963 964 if __name__ == "__main__": 965 test_main() 966