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() |
---|