| 1 | n/a | # Test some Unicode file name semantics |
|---|
| 2 | n/a | # We dont test many operations on files other than |
|---|
| 3 | n/a | # that their names can be used with Unicode characters. |
|---|
| 4 | n/a | import os, glob, time, shutil |
|---|
| 5 | n/a | import unicodedata |
|---|
| 6 | n/a | |
|---|
| 7 | n/a | import unittest |
|---|
| 8 | n/a | from test.support import (run_unittest, rmtree, change_cwd, |
|---|
| 9 | n/a | TESTFN_ENCODING, TESTFN_UNICODE, TESTFN_UNENCODABLE, create_empty_file) |
|---|
| 10 | n/a | |
|---|
| 11 | n/a | if not os.path.supports_unicode_filenames: |
|---|
| 12 | n/a | try: |
|---|
| 13 | n/a | TESTFN_UNICODE.encode(TESTFN_ENCODING) |
|---|
| 14 | n/a | except (UnicodeError, TypeError): |
|---|
| 15 | n/a | # Either the file system encoding is None, or the file name |
|---|
| 16 | n/a | # cannot be encoded in the file system encoding. |
|---|
| 17 | n/a | raise unittest.SkipTest("No Unicode filesystem semantics on this platform.") |
|---|
| 18 | n/a | |
|---|
| 19 | n/a | def remove_if_exists(filename): |
|---|
| 20 | n/a | if os.path.exists(filename): |
|---|
| 21 | n/a | os.unlink(filename) |
|---|
| 22 | n/a | |
|---|
| 23 | n/a | class TestUnicodeFiles(unittest.TestCase): |
|---|
| 24 | n/a | # The 'do_' functions are the actual tests. They generally assume the |
|---|
| 25 | n/a | # file already exists etc. |
|---|
| 26 | n/a | |
|---|
| 27 | n/a | # Do all the tests we can given only a single filename. The file should |
|---|
| 28 | n/a | # exist. |
|---|
| 29 | n/a | def _do_single(self, filename): |
|---|
| 30 | n/a | self.assertTrue(os.path.exists(filename)) |
|---|
| 31 | n/a | self.assertTrue(os.path.isfile(filename)) |
|---|
| 32 | n/a | self.assertTrue(os.access(filename, os.R_OK)) |
|---|
| 33 | n/a | self.assertTrue(os.path.exists(os.path.abspath(filename))) |
|---|
| 34 | n/a | self.assertTrue(os.path.isfile(os.path.abspath(filename))) |
|---|
| 35 | n/a | self.assertTrue(os.access(os.path.abspath(filename), os.R_OK)) |
|---|
| 36 | n/a | os.chmod(filename, 0o777) |
|---|
| 37 | n/a | os.utime(filename, None) |
|---|
| 38 | n/a | os.utime(filename, (time.time(), time.time())) |
|---|
| 39 | n/a | # Copy/rename etc tests using the same filename |
|---|
| 40 | n/a | self._do_copyish(filename, filename) |
|---|
| 41 | n/a | # Filename should appear in glob output |
|---|
| 42 | n/a | self.assertTrue( |
|---|
| 43 | n/a | os.path.abspath(filename)==os.path.abspath(glob.glob(filename)[0])) |
|---|
| 44 | n/a | # basename should appear in listdir. |
|---|
| 45 | n/a | path, base = os.path.split(os.path.abspath(filename)) |
|---|
| 46 | n/a | file_list = os.listdir(path) |
|---|
| 47 | n/a | # Normalize the unicode strings, as round-tripping the name via the OS |
|---|
| 48 | n/a | # may return a different (but equivalent) value. |
|---|
| 49 | n/a | base = unicodedata.normalize("NFD", base) |
|---|
| 50 | n/a | file_list = [unicodedata.normalize("NFD", f) for f in file_list] |
|---|
| 51 | n/a | |
|---|
| 52 | n/a | self.assertIn(base, file_list) |
|---|
| 53 | n/a | |
|---|
| 54 | n/a | # Tests that copy, move, etc one file to another. |
|---|
| 55 | n/a | def _do_copyish(self, filename1, filename2): |
|---|
| 56 | n/a | # Should be able to rename the file using either name. |
|---|
| 57 | n/a | self.assertTrue(os.path.isfile(filename1)) # must exist. |
|---|
| 58 | n/a | os.rename(filename1, filename2 + ".new") |
|---|
| 59 | n/a | self.assertFalse(os.path.isfile(filename2)) |
|---|
| 60 | n/a | self.assertTrue(os.path.isfile(filename1 + '.new')) |
|---|
| 61 | n/a | os.rename(filename1 + ".new", filename2) |
|---|
| 62 | n/a | self.assertFalse(os.path.isfile(filename1 + '.new')) |
|---|
| 63 | n/a | self.assertTrue(os.path.isfile(filename2)) |
|---|
| 64 | n/a | |
|---|
| 65 | n/a | shutil.copy(filename1, filename2 + ".new") |
|---|
| 66 | n/a | os.unlink(filename1 + ".new") # remove using equiv name. |
|---|
| 67 | n/a | # And a couple of moves, one using each name. |
|---|
| 68 | n/a | shutil.move(filename1, filename2 + ".new") |
|---|
| 69 | n/a | self.assertFalse(os.path.exists(filename2)) |
|---|
| 70 | n/a | self.assertTrue(os.path.exists(filename1 + '.new')) |
|---|
| 71 | n/a | shutil.move(filename1 + ".new", filename2) |
|---|
| 72 | n/a | self.assertFalse(os.path.exists(filename2 + '.new')) |
|---|
| 73 | n/a | self.assertTrue(os.path.exists(filename1)) |
|---|
| 74 | n/a | # Note - due to the implementation of shutil.move, |
|---|
| 75 | n/a | # it tries a rename first. This only fails on Windows when on |
|---|
| 76 | n/a | # different file systems - and this test can't ensure that. |
|---|
| 77 | n/a | # So we test the shutil.copy2 function, which is the thing most |
|---|
| 78 | n/a | # likely to fail. |
|---|
| 79 | n/a | shutil.copy2(filename1, filename2 + ".new") |
|---|
| 80 | n/a | self.assertTrue(os.path.isfile(filename1 + '.new')) |
|---|
| 81 | n/a | os.unlink(filename1 + ".new") |
|---|
| 82 | n/a | self.assertFalse(os.path.exists(filename2 + '.new')) |
|---|
| 83 | n/a | |
|---|
| 84 | n/a | def _do_directory(self, make_name, chdir_name): |
|---|
| 85 | n/a | if os.path.isdir(make_name): |
|---|
| 86 | n/a | rmtree(make_name) |
|---|
| 87 | n/a | os.mkdir(make_name) |
|---|
| 88 | n/a | try: |
|---|
| 89 | n/a | with change_cwd(chdir_name): |
|---|
| 90 | n/a | cwd_result = os.getcwd() |
|---|
| 91 | n/a | name_result = make_name |
|---|
| 92 | n/a | |
|---|
| 93 | n/a | cwd_result = unicodedata.normalize("NFD", cwd_result) |
|---|
| 94 | n/a | name_result = unicodedata.normalize("NFD", name_result) |
|---|
| 95 | n/a | |
|---|
| 96 | n/a | self.assertEqual(os.path.basename(cwd_result),name_result) |
|---|
| 97 | n/a | finally: |
|---|
| 98 | n/a | os.rmdir(make_name) |
|---|
| 99 | n/a | |
|---|
| 100 | n/a | # The '_test' functions 'entry points with params' - ie, what the |
|---|
| 101 | n/a | # top-level 'test' functions would be if they could take params |
|---|
| 102 | n/a | def _test_single(self, filename): |
|---|
| 103 | n/a | remove_if_exists(filename) |
|---|
| 104 | n/a | create_empty_file(filename) |
|---|
| 105 | n/a | try: |
|---|
| 106 | n/a | self._do_single(filename) |
|---|
| 107 | n/a | finally: |
|---|
| 108 | n/a | os.unlink(filename) |
|---|
| 109 | n/a | self.assertTrue(not os.path.exists(filename)) |
|---|
| 110 | n/a | # and again with os.open. |
|---|
| 111 | n/a | f = os.open(filename, os.O_CREAT) |
|---|
| 112 | n/a | os.close(f) |
|---|
| 113 | n/a | try: |
|---|
| 114 | n/a | self._do_single(filename) |
|---|
| 115 | n/a | finally: |
|---|
| 116 | n/a | os.unlink(filename) |
|---|
| 117 | n/a | |
|---|
| 118 | n/a | # The 'test' functions are unittest entry points, and simply call our |
|---|
| 119 | n/a | # _test functions with each of the filename combinations we wish to test |
|---|
| 120 | n/a | def test_single_files(self): |
|---|
| 121 | n/a | self._test_single(TESTFN_UNICODE) |
|---|
| 122 | n/a | if TESTFN_UNENCODABLE is not None: |
|---|
| 123 | n/a | self._test_single(TESTFN_UNENCODABLE) |
|---|
| 124 | n/a | |
|---|
| 125 | n/a | def test_directories(self): |
|---|
| 126 | n/a | # For all 'equivalent' combinations: |
|---|
| 127 | n/a | # Make dir with encoded, chdir with unicode, checkdir with encoded |
|---|
| 128 | n/a | # (or unicode/encoded/unicode, etc |
|---|
| 129 | n/a | ext = ".dir" |
|---|
| 130 | n/a | self._do_directory(TESTFN_UNICODE+ext, TESTFN_UNICODE+ext) |
|---|
| 131 | n/a | # Our directory name that can't use a non-unicode name. |
|---|
| 132 | n/a | if TESTFN_UNENCODABLE is not None: |
|---|
| 133 | n/a | self._do_directory(TESTFN_UNENCODABLE+ext, |
|---|
| 134 | n/a | TESTFN_UNENCODABLE+ext) |
|---|
| 135 | n/a | |
|---|
| 136 | n/a | def test_main(): |
|---|
| 137 | n/a | run_unittest(__name__) |
|---|
| 138 | n/a | |
|---|
| 139 | n/a | if __name__ == "__main__": |
|---|
| 140 | n/a | test_main() |
|---|