|
1 | 1 | # Test some Unicode file name semantics |
2 | 2 | # We dont test many operations on files other than |
3 | 3 | # that their names can be used with Unicode characters. |
4 | | -import os, glob |
| 4 | +import os, glob, time, shutil |
5 | 5 |
|
6 | | -from test.test_support import verify, TestSkipped, TESTFN_UNICODE |
7 | | -from test.test_support import TESTFN_ENCODING |
| 6 | +import unittest |
| 7 | +from test.test_support import run_suite, TestSkipped, TESTFN_UNICODE |
| 8 | +from test.test_support import TESTFN_ENCODING, TESTFN_UNICODE_UNENCODEABLE |
8 | 9 | try: |
9 | 10 | TESTFN_ENCODED = TESTFN_UNICODE.encode(TESTFN_ENCODING) |
10 | 11 | except (UnicodeError, TypeError): |
11 | 12 | # Either the file system encoding is None, or the file name |
12 | 13 | # cannot be encoded in the file system encoding. |
13 | 14 | raise TestSkipped("No Unicode filesystem semantics on this platform.") |
14 | 15 |
|
15 | | -# Check with creation as Unicode string. |
16 | | -f = open(TESTFN_UNICODE, 'wb') |
17 | | -if not os.path.isfile(TESTFN_UNICODE): |
18 | | - print "File doesn't exist after creating it" |
| 16 | +def remove_if_exists(filename): |
| 17 | + if os.path.exists(filename): |
| 18 | + os.unlink(filename) |
19 | 19 |
|
20 | | -if not os.path.isfile(TESTFN_ENCODED): |
21 | | - print "File doesn't exist (encoded string) after creating it" |
| 20 | +class TestUnicodeFiles(unittest.TestCase): |
| 21 | + # The 'do_' functions are the actual tests. They generally assume the |
| 22 | + # file already exists etc. |
| 23 | + |
| 24 | + # Do all the tests we can given only a single filename. The file should |
| 25 | + # exist. |
| 26 | + def _do_single(self, filename): |
| 27 | + self.failUnless(os.path.exists(filename)) |
| 28 | + self.failUnless(os.path.isfile(filename)) |
| 29 | + self.failUnless(os.path.exists(os.path.abspath(filename))) |
| 30 | + self.failUnless(os.path.isfile(os.path.abspath(filename))) |
| 31 | + os.chmod(filename, 0777) |
| 32 | + os.utime(filename, None) |
| 33 | + os.utime(filename, (time.time(), time.time())) |
| 34 | + # Copy/rename etc tests using the same filename |
| 35 | + self._do_copyish(filename, filename) |
| 36 | + # Filename should appear in glob output |
| 37 | + self.failUnless( |
| 38 | + os.path.abspath(filename)==os.path.abspath(glob.glob(filename)[0])) |
| 39 | + # basename should appear in listdir. |
| 40 | + path, base = os.path.split(os.path.abspath(filename)) |
| 41 | + self.failUnless(base in os.listdir(path)) |
| 42 | + |
| 43 | + # Do as many "equivalancy' tests as we can - ie, check that although we |
| 44 | + # have different types for the filename, they refer to the same file. |
| 45 | + def _do_equivilent(self, filename1, filename2): |
| 46 | + # Note we only check "filename1 against filename2" - we don't bother |
| 47 | + # checking "filename2 against 1", as we assume we are called again with |
| 48 | + # the args reversed. |
| 49 | + self.failUnless(type(filename1)!=type(filename2), |
| 50 | + "No point checking equivalent filenames of the same type") |
| 51 | + # stat and lstat should return the same results. |
| 52 | + self.failUnlessEqual(os.stat(filename1), |
| 53 | + os.stat(filename2)) |
| 54 | + self.failUnlessEqual(os.lstat(filename1), |
| 55 | + os.lstat(filename2)) |
| 56 | + # Copy/rename etc tests using equivalent filename |
| 57 | + self._do_copyish(filename1, filename2) |
22 | 58 |
|
23 | | -f.close() |
| 59 | + # Tests that copy, move, etc one file to another. |
| 60 | + def _do_copyish(self, filename1, filename2): |
| 61 | + # Should be able to rename the file using either name. |
| 62 | + self.failUnless(os.path.isfile(filename1)) # must exist. |
| 63 | + os.rename(filename1, filename2 + ".new") |
| 64 | + self.failUnless(os.path.isfile(filename1+".new")) |
| 65 | + os.rename(filename1 + ".new", filename2) |
| 66 | + self.failUnless(os.path.isfile(filename2)) |
24 | 67 |
|
25 | | -# Test stat and chmod |
26 | | -if os.stat(TESTFN_ENCODED) != os.stat(TESTFN_UNICODE): |
27 | | - print "os.stat() did not agree on the 2 filenames" |
28 | | -if os.lstat(TESTFN_ENCODED) != os.lstat(TESTFN_UNICODE): |
29 | | - print "os.lstat() did not agree on the 2 filenames" |
30 | | -os.chmod(TESTFN_ENCODED, 0777) |
31 | | -os.chmod(TESTFN_UNICODE, 0777) |
| 68 | + # Try using shutil on the filenames. |
| 69 | + try: |
| 70 | + filename1==filename2 |
| 71 | + except UnicodeDecodeError: |
| 72 | + # these filenames can't be compared - shutil.copy tries to do |
| 73 | + # just that. This is really a bug in 'shutil' - if one of shutil's |
| 74 | + # 2 params are Unicode and the other isn't, it should coerce the |
| 75 | + # string to Unicode with the filesystem encoding before comparison. |
| 76 | + pass |
| 77 | + else: |
| 78 | + # filenames can be compared. |
| 79 | + shutil.copy(filename1, filename2 + ".new") |
| 80 | + os.unlink(filename1 + ".new") # remove using equiv name. |
| 81 | + # And a couple of moves, one using each name. |
| 82 | + shutil.move(filename1, filename2 + ".new") |
| 83 | + self.failUnless(not os.path.exists(filename2)) |
| 84 | + shutil.move(filename1 + ".new", filename2) |
| 85 | + self.failUnless(os.path.exists(filename1)) |
| 86 | + # Note - due to the implementation of shutil.move, |
| 87 | + # it tries a rename first. This only fails on Windows when on |
| 88 | + # different file systems - and this test can't ensure that. |
| 89 | + # So we test the shutil.copy2 function, which is the thing most |
| 90 | + # likely to fail. |
| 91 | + shutil.copy2(filename1, filename2 + ".new") |
| 92 | + os.unlink(filename1 + ".new") |
32 | 93 |
|
33 | | -# Test rename |
34 | | -try: |
35 | | - os.unlink(TESTFN_ENCODED + ".new") |
36 | | -except os.error: |
37 | | - pass |
38 | | -os.rename(TESTFN_ENCODED, TESTFN_ENCODED + ".new") |
39 | | -os.rename(TESTFN_UNICODE+".new", TESTFN_ENCODED) |
40 | | - |
41 | | -os.unlink(TESTFN_ENCODED) |
42 | | -if os.path.isfile(TESTFN_ENCODED) or \ |
43 | | - os.path.isfile(TESTFN_UNICODE): |
44 | | - print "File exists after deleting it" |
| 94 | + def _do_directory(self, make_name, chdir_name, getcwd_func): |
| 95 | + cwd = os.getcwd() |
| 96 | + if os.path.isdir(make_name): |
| 97 | + os.rmdir(make_name) |
| 98 | + os.mkdir(make_name) |
| 99 | + try: |
| 100 | + os.chdir(chdir_name) |
| 101 | + try: |
| 102 | + self.failUnlessEqual(os.path.basename(getcwd_func()), |
| 103 | + make_name) |
| 104 | + finally: |
| 105 | + os.chdir(cwd) |
| 106 | + finally: |
| 107 | + os.rmdir(make_name) |
45 | 108 |
|
46 | | -# Check with creation as encoded string. |
47 | | -f = open(TESTFN_ENCODED, 'wb') |
48 | | -if not os.path.isfile(TESTFN_UNICODE) or \ |
49 | | - not os.path.isfile(TESTFN_ENCODED): |
50 | | - print "File doesn't exist after creating it" |
| 109 | + # The '_test' functions 'entry points with params' - ie, what the |
| 110 | + # top-level 'test' functions would be if they could take params |
| 111 | + def _test_single(self, filename): |
| 112 | + remove_if_exists(filename) |
| 113 | + f = file(filename, "w") |
| 114 | + f.close() |
| 115 | + try: |
| 116 | + self._do_single(filename) |
| 117 | + finally: |
| 118 | + os.unlink(filename) |
| 119 | + self.failUnless(not os.path.exists(filename)) |
| 120 | + # and again with os.open. |
| 121 | + f = os.open(filename, os.O_CREAT) |
| 122 | + os.close(f) |
| 123 | + try: |
| 124 | + self._do_single(filename) |
| 125 | + finally: |
| 126 | + os.unlink(filename) |
| 127 | + |
| 128 | + def _test_equivalent(self, filename1, filename2): |
| 129 | + remove_if_exists(filename1) |
| 130 | + self.failUnless(not os.path.exists(filename2)) |
| 131 | + f = file(filename1, "w") |
| 132 | + f.close() |
| 133 | + try: |
| 134 | + self._do_equivilent(filename1, filename2) |
| 135 | + finally: |
| 136 | + os.unlink(filename1) |
51 | 137 |
|
52 | | -path, base = os.path.split(os.path.abspath(TESTFN_ENCODED)) |
53 | | -# Until PEP 277 is adopted, this test is not portable |
54 | | -# if base not in os.listdir(path): |
55 | | -# print "Filename did not appear in os.listdir()" |
56 | | -# path, base = os.path.split(os.path.abspath(TESTFN_UNICODE)) |
57 | | -# if base not in os.listdir(path): |
58 | | -# print "Unicode filename did not appear in os.listdir()" |
| 138 | + # The 'test' functions are unittest entry points, and simply call our |
| 139 | + # _test functions with each of the filename combinations we wish to test |
| 140 | + def test_single_files(self): |
| 141 | + self._test_single(TESTFN_ENCODED) |
| 142 | + self._test_single(TESTFN_UNICODE) |
| 143 | + self._test_single(TESTFN_UNICODE_UNENCODEABLE) |
59 | 144 |
|
60 | | -if os.path.abspath(TESTFN_ENCODED) != os.path.abspath(glob.glob(TESTFN_ENCODED)[0]): |
61 | | - print "Filename did not appear in glob.glob()" |
62 | | -if os.path.abspath(TESTFN_UNICODE) != os.path.abspath(glob.glob(TESTFN_UNICODE)[0]): |
63 | | - print "Unicode filename did not appear in glob.glob()" |
| 145 | + def test_equivalent_files(self): |
| 146 | + self._test_equivalent(TESTFN_ENCODED, TESTFN_UNICODE) |
| 147 | + self._test_equivalent(TESTFN_UNICODE, TESTFN_ENCODED) |
64 | 148 |
|
65 | | -f.close() |
66 | | -os.unlink(TESTFN_UNICODE) |
67 | | -if os.path.isfile(TESTFN_ENCODED) or \ |
68 | | - os.path.isfile(TESTFN_UNICODE): |
69 | | - print "File exists after deleting it" |
| 149 | + def test_directories(self): |
| 150 | + # For all 'equivilent' combinations: |
| 151 | + # Make dir with encoded, chdir with unicode, checkdir with encoded |
| 152 | + # (or unicode/encoded/unicode, etc |
| 153 | + ext = ".dir" |
| 154 | + self._do_directory(TESTFN_ENCODED+ext, TESTFN_ENCODED+ext, os.getcwd) |
| 155 | + self._do_directory(TESTFN_ENCODED+ext, TESTFN_UNICODE+ext, os.getcwd) |
| 156 | + self._do_directory(TESTFN_UNICODE+ext, TESTFN_ENCODED+ext, os.getcwdu) |
| 157 | + self._do_directory(TESTFN_UNICODE+ext, TESTFN_UNICODE+ext, os.getcwdu) |
| 158 | + # Our directory name that can't use a non-unicode name. |
| 159 | + self._do_directory(TESTFN_UNICODE_UNENCODEABLE+ext, |
| 160 | + TESTFN_UNICODE_UNENCODEABLE+ext, |
| 161 | + os.getcwdu) |
70 | 162 |
|
71 | | -# test os.open |
72 | | -f = os.open(TESTFN_ENCODED, os.O_CREAT) |
73 | | -if not os.path.isfile(TESTFN_UNICODE) or \ |
74 | | - not os.path.isfile(TESTFN_ENCODED): |
75 | | - print "File doesn't exist after creating it" |
76 | | -os.close(f) |
77 | | -os.unlink(TESTFN_UNICODE) |
| 163 | +def test_main(): |
| 164 | + suite = unittest.TestSuite() |
| 165 | + suite.addTest(unittest.makeSuite(TestUnicodeFiles)) |
| 166 | + run_suite(suite) |
78 | 167 |
|
79 | | -# Test directories etc |
80 | | -cwd = os.getcwd() |
81 | | -abs_encoded = os.path.abspath(TESTFN_ENCODED) + ".dir" |
82 | | -abs_unicode = os.path.abspath(TESTFN_UNICODE) + ".dir" |
83 | | -os.mkdir(abs_encoded) |
84 | | -try: |
85 | | - os.chdir(abs_encoded) |
86 | | - os.chdir(abs_unicode) |
87 | | -finally: |
88 | | - os.chdir(cwd) |
89 | | - os.rmdir(abs_unicode) |
90 | | -os.mkdir(abs_unicode) |
91 | | -try: |
92 | | - os.chdir(abs_encoded) |
93 | | - os.chdir(abs_unicode) |
94 | | -finally: |
95 | | - os.chdir(cwd) |
96 | | - os.rmdir(abs_encoded) |
97 | | -print "All the Unicode tests appeared to work" |
| 168 | +if __name__ == "__main__": |
| 169 | + test_main() |
0 commit comments