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