|
1 import unittest |
|
2 from test import test_support |
|
3 |
|
4 import posixpath, os |
|
5 from posixpath import realpath, abspath, join, dirname, basename, relpath |
|
6 |
|
7 # An absolute path to a temporary filename for testing. We can't rely on TESTFN |
|
8 # being an absolute path, so we need this. |
|
9 |
|
10 ABSTFN = abspath(test_support.TESTFN) |
|
11 |
|
12 def safe_rmdir(dirname): |
|
13 try: |
|
14 os.rmdir(dirname) |
|
15 except OSError: |
|
16 pass |
|
17 |
|
18 class PosixPathTest(unittest.TestCase): |
|
19 |
|
20 def setUp(self): |
|
21 self.tearDown() |
|
22 |
|
23 def tearDown(self): |
|
24 for suffix in ["", "1", "2"]: |
|
25 test_support.unlink(test_support.TESTFN + suffix) |
|
26 safe_rmdir(test_support.TESTFN + suffix) |
|
27 |
|
28 def assertIs(self, a, b): |
|
29 self.assert_(a is b) |
|
30 |
|
31 def test_normcase(self): |
|
32 # Check that normcase() is idempotent |
|
33 p = "FoO/./BaR" |
|
34 p = posixpath.normcase(p) |
|
35 self.assertEqual(p, posixpath.normcase(p)) |
|
36 |
|
37 self.assertRaises(TypeError, posixpath.normcase) |
|
38 |
|
39 def test_join(self): |
|
40 self.assertEqual(posixpath.join("/foo", "bar", "/bar", "baz"), "/bar/baz") |
|
41 self.assertEqual(posixpath.join("/foo", "bar", "baz"), "/foo/bar/baz") |
|
42 self.assertEqual(posixpath.join("/foo/", "bar/", "baz/"), "/foo/bar/baz/") |
|
43 |
|
44 self.assertRaises(TypeError, posixpath.join) |
|
45 |
|
46 def test_splitdrive(self): |
|
47 self.assertEqual(posixpath.splitdrive("/foo/bar"), ("", "/foo/bar")) |
|
48 |
|
49 self.assertRaises(TypeError, posixpath.splitdrive) |
|
50 |
|
51 def test_split(self): |
|
52 self.assertEqual(posixpath.split("/foo/bar"), ("/foo", "bar")) |
|
53 self.assertEqual(posixpath.split("/"), ("/", "")) |
|
54 self.assertEqual(posixpath.split("foo"), ("", "foo")) |
|
55 self.assertEqual(posixpath.split("////foo"), ("////", "foo")) |
|
56 self.assertEqual(posixpath.split("//foo//bar"), ("//foo", "bar")) |
|
57 |
|
58 self.assertRaises(TypeError, posixpath.split) |
|
59 |
|
60 def splitextTest(self, path, filename, ext): |
|
61 self.assertEqual(posixpath.splitext(path), (filename, ext)) |
|
62 self.assertEqual(posixpath.splitext("/" + path), ("/" + filename, ext)) |
|
63 self.assertEqual(posixpath.splitext("abc/" + path), ("abc/" + filename, ext)) |
|
64 self.assertEqual(posixpath.splitext("abc.def/" + path), ("abc.def/" + filename, ext)) |
|
65 self.assertEqual(posixpath.splitext("/abc.def/" + path), ("/abc.def/" + filename, ext)) |
|
66 self.assertEqual(posixpath.splitext(path + "/"), (filename + ext + "/", "")) |
|
67 |
|
68 def test_splitext(self): |
|
69 self.splitextTest("foo.bar", "foo", ".bar") |
|
70 self.splitextTest("foo.boo.bar", "foo.boo", ".bar") |
|
71 self.splitextTest("foo.boo.biff.bar", "foo.boo.biff", ".bar") |
|
72 self.splitextTest(".csh.rc", ".csh", ".rc") |
|
73 self.splitextTest("nodots", "nodots", "") |
|
74 self.splitextTest(".cshrc", ".cshrc", "") |
|
75 self.splitextTest("...manydots", "...manydots", "") |
|
76 self.splitextTest("...manydots.ext", "...manydots", ".ext") |
|
77 self.splitextTest(".", ".", "") |
|
78 self.splitextTest("..", "..", "") |
|
79 self.splitextTest("........", "........", "") |
|
80 self.splitextTest("", "", "") |
|
81 self.assertRaises(TypeError, posixpath.splitext) |
|
82 |
|
83 def test_isabs(self): |
|
84 self.assertIs(posixpath.isabs(""), False) |
|
85 self.assertIs(posixpath.isabs("/"), True) |
|
86 self.assertIs(posixpath.isabs("/foo"), True) |
|
87 self.assertIs(posixpath.isabs("/foo/bar"), True) |
|
88 self.assertIs(posixpath.isabs("foo/bar"), False) |
|
89 |
|
90 self.assertRaises(TypeError, posixpath.isabs) |
|
91 |
|
92 def test_splitdrive(self): |
|
93 self.assertEqual(posixpath.splitdrive("/foo/bar"), ("", "/foo/bar")) |
|
94 |
|
95 self.assertRaises(TypeError, posixpath.splitdrive) |
|
96 |
|
97 def test_basename(self): |
|
98 self.assertEqual(posixpath.basename("/foo/bar"), "bar") |
|
99 self.assertEqual(posixpath.basename("/"), "") |
|
100 self.assertEqual(posixpath.basename("foo"), "foo") |
|
101 self.assertEqual(posixpath.basename("////foo"), "foo") |
|
102 self.assertEqual(posixpath.basename("//foo//bar"), "bar") |
|
103 |
|
104 self.assertRaises(TypeError, posixpath.basename) |
|
105 |
|
106 def test_dirname(self): |
|
107 self.assertEqual(posixpath.dirname("/foo/bar"), "/foo") |
|
108 self.assertEqual(posixpath.dirname("/"), "/") |
|
109 self.assertEqual(posixpath.dirname("foo"), "") |
|
110 self.assertEqual(posixpath.dirname("////foo"), "////") |
|
111 self.assertEqual(posixpath.dirname("//foo//bar"), "//foo") |
|
112 |
|
113 self.assertRaises(TypeError, posixpath.dirname) |
|
114 |
|
115 def test_commonprefix(self): |
|
116 self.assertEqual( |
|
117 posixpath.commonprefix([]), |
|
118 "" |
|
119 ) |
|
120 self.assertEqual( |
|
121 posixpath.commonprefix(["/home/swenson/spam", "/home/swen/spam"]), |
|
122 "/home/swen" |
|
123 ) |
|
124 self.assertEqual( |
|
125 posixpath.commonprefix(["/home/swen/spam", "/home/swen/eggs"]), |
|
126 "/home/swen/" |
|
127 ) |
|
128 self.assertEqual( |
|
129 posixpath.commonprefix(["/home/swen/spam", "/home/swen/spam"]), |
|
130 "/home/swen/spam" |
|
131 ) |
|
132 |
|
133 testlist = ['', 'abc', 'Xbcd', 'Xb', 'XY', 'abcd', 'aXc', 'abd', 'ab', 'aX', 'abcX'] |
|
134 for s1 in testlist: |
|
135 for s2 in testlist: |
|
136 p = posixpath.commonprefix([s1, s2]) |
|
137 self.assert_(s1.startswith(p)) |
|
138 self.assert_(s2.startswith(p)) |
|
139 if s1 != s2: |
|
140 n = len(p) |
|
141 self.assertNotEqual(s1[n:n+1], s2[n:n+1]) |
|
142 |
|
143 def test_getsize(self): |
|
144 f = open(test_support.TESTFN, "wb") |
|
145 try: |
|
146 f.write("foo") |
|
147 f.close() |
|
148 self.assertEqual(posixpath.getsize(test_support.TESTFN), 3) |
|
149 finally: |
|
150 if not f.closed: |
|
151 f.close() |
|
152 |
|
153 def test_time(self): |
|
154 f = open(test_support.TESTFN, "wb") |
|
155 try: |
|
156 f.write("foo") |
|
157 f.close() |
|
158 f = open(test_support.TESTFN, "ab") |
|
159 f.write("bar") |
|
160 f.close() |
|
161 f = open(test_support.TESTFN, "rb") |
|
162 d = f.read() |
|
163 f.close() |
|
164 self.assertEqual(d, "foobar") |
|
165 |
|
166 self.assert_( |
|
167 posixpath.getctime(test_support.TESTFN) <= |
|
168 posixpath.getmtime(test_support.TESTFN) |
|
169 ) |
|
170 finally: |
|
171 if not f.closed: |
|
172 f.close() |
|
173 |
|
174 def test_islink(self): |
|
175 self.assertIs(posixpath.islink(test_support.TESTFN + "1"), False) |
|
176 f = open(test_support.TESTFN + "1", "wb") |
|
177 try: |
|
178 f.write("foo") |
|
179 f.close() |
|
180 self.assertIs(posixpath.islink(test_support.TESTFN + "1"), False) |
|
181 if hasattr(os, "symlink"): |
|
182 os.symlink(test_support.TESTFN + "1", test_support.TESTFN + "2") |
|
183 self.assertIs(posixpath.islink(test_support.TESTFN + "2"), True) |
|
184 os.remove(test_support.TESTFN + "1") |
|
185 self.assertIs(posixpath.islink(test_support.TESTFN + "2"), True) |
|
186 self.assertIs(posixpath.exists(test_support.TESTFN + "2"), False) |
|
187 self.assertIs(posixpath.lexists(test_support.TESTFN + "2"), True) |
|
188 finally: |
|
189 if not f.close(): |
|
190 f.close() |
|
191 |
|
192 self.assertRaises(TypeError, posixpath.islink) |
|
193 |
|
194 def test_exists(self): |
|
195 self.assertIs(posixpath.exists(test_support.TESTFN), False) |
|
196 f = open(test_support.TESTFN, "wb") |
|
197 try: |
|
198 f.write("foo") |
|
199 f.close() |
|
200 self.assertIs(posixpath.exists(test_support.TESTFN), True) |
|
201 self.assertIs(posixpath.lexists(test_support.TESTFN), True) |
|
202 finally: |
|
203 if not f.close(): |
|
204 f.close() |
|
205 |
|
206 self.assertRaises(TypeError, posixpath.exists) |
|
207 |
|
208 def test_isdir(self): |
|
209 self.assertIs(posixpath.isdir(test_support.TESTFN), False) |
|
210 f = open(test_support.TESTFN, "wb") |
|
211 try: |
|
212 f.write("foo") |
|
213 f.close() |
|
214 self.assertIs(posixpath.isdir(test_support.TESTFN), False) |
|
215 os.remove(test_support.TESTFN) |
|
216 os.mkdir(test_support.TESTFN) |
|
217 self.assertIs(posixpath.isdir(test_support.TESTFN), True) |
|
218 os.rmdir(test_support.TESTFN) |
|
219 finally: |
|
220 if not f.close(): |
|
221 f.close() |
|
222 |
|
223 self.assertRaises(TypeError, posixpath.isdir) |
|
224 |
|
225 def test_isfile(self): |
|
226 self.assertIs(posixpath.isfile(test_support.TESTFN), False) |
|
227 f = open(test_support.TESTFN, "wb") |
|
228 try: |
|
229 f.write("foo") |
|
230 f.close() |
|
231 self.assertIs(posixpath.isfile(test_support.TESTFN), True) |
|
232 os.remove(test_support.TESTFN) |
|
233 os.mkdir(test_support.TESTFN) |
|
234 self.assertIs(posixpath.isfile(test_support.TESTFN), False) |
|
235 os.rmdir(test_support.TESTFN) |
|
236 finally: |
|
237 if not f.close(): |
|
238 f.close() |
|
239 |
|
240 self.assertRaises(TypeError, posixpath.isdir) |
|
241 |
|
242 def test_samefile(self): |
|
243 f = open(test_support.TESTFN + "1", "wb") |
|
244 try: |
|
245 f.write("foo") |
|
246 f.close() |
|
247 self.assertIs( |
|
248 posixpath.samefile( |
|
249 test_support.TESTFN + "1", |
|
250 test_support.TESTFN + "1" |
|
251 ), |
|
252 True |
|
253 ) |
|
254 # If we don't have links, assume that os.stat doesn't return resonable |
|
255 # inode information and thus, that samefile() doesn't work |
|
256 if hasattr(os, "symlink"): |
|
257 os.symlink( |
|
258 test_support.TESTFN + "1", |
|
259 test_support.TESTFN + "2" |
|
260 ) |
|
261 self.assertIs( |
|
262 posixpath.samefile( |
|
263 test_support.TESTFN + "1", |
|
264 test_support.TESTFN + "2" |
|
265 ), |
|
266 True |
|
267 ) |
|
268 os.remove(test_support.TESTFN + "2") |
|
269 f = open(test_support.TESTFN + "2", "wb") |
|
270 f.write("bar") |
|
271 f.close() |
|
272 self.assertIs( |
|
273 posixpath.samefile( |
|
274 test_support.TESTFN + "1", |
|
275 test_support.TESTFN + "2" |
|
276 ), |
|
277 False |
|
278 ) |
|
279 finally: |
|
280 if not f.close(): |
|
281 f.close() |
|
282 |
|
283 self.assertRaises(TypeError, posixpath.samefile) |
|
284 |
|
285 def test_samestat(self): |
|
286 f = open(test_support.TESTFN + "1", "wb") |
|
287 try: |
|
288 f.write("foo") |
|
289 f.close() |
|
290 self.assertIs( |
|
291 posixpath.samestat( |
|
292 os.stat(test_support.TESTFN + "1"), |
|
293 os.stat(test_support.TESTFN + "1") |
|
294 ), |
|
295 True |
|
296 ) |
|
297 # If we don't have links, assume that os.stat() doesn't return resonable |
|
298 # inode information and thus, that samefile() doesn't work |
|
299 if hasattr(os, "symlink"): |
|
300 if hasattr(os, "symlink"): |
|
301 os.symlink(test_support.TESTFN + "1", test_support.TESTFN + "2") |
|
302 self.assertIs( |
|
303 posixpath.samestat( |
|
304 os.stat(test_support.TESTFN + "1"), |
|
305 os.stat(test_support.TESTFN + "2") |
|
306 ), |
|
307 True |
|
308 ) |
|
309 os.remove(test_support.TESTFN + "2") |
|
310 f = open(test_support.TESTFN + "2", "wb") |
|
311 f.write("bar") |
|
312 f.close() |
|
313 self.assertIs( |
|
314 posixpath.samestat( |
|
315 os.stat(test_support.TESTFN + "1"), |
|
316 os.stat(test_support.TESTFN + "2") |
|
317 ), |
|
318 False |
|
319 ) |
|
320 finally: |
|
321 if not f.close(): |
|
322 f.close() |
|
323 |
|
324 self.assertRaises(TypeError, posixpath.samestat) |
|
325 |
|
326 def test_ismount(self): |
|
327 self.assertIs(posixpath.ismount("/"), True) |
|
328 |
|
329 self.assertRaises(TypeError, posixpath.ismount) |
|
330 |
|
331 def test_expanduser(self): |
|
332 self.assertEqual(posixpath.expanduser("foo"), "foo") |
|
333 try: |
|
334 import pwd |
|
335 except ImportError: |
|
336 pass |
|
337 else: |
|
338 self.assert_(isinstance(posixpath.expanduser("~/"), basestring)) |
|
339 # if home directory == root directory, this test makes no sense |
|
340 if posixpath.expanduser("~") != '/': |
|
341 self.assertEqual( |
|
342 posixpath.expanduser("~") + "/", |
|
343 posixpath.expanduser("~/") |
|
344 ) |
|
345 self.assert_(isinstance(posixpath.expanduser("~root/"), basestring)) |
|
346 self.assert_(isinstance(posixpath.expanduser("~foo/"), basestring)) |
|
347 |
|
348 self.assertRaises(TypeError, posixpath.expanduser) |
|
349 |
|
350 def test_expandvars(self): |
|
351 oldenv = os.environ.copy() |
|
352 try: |
|
353 os.environ.clear() |
|
354 os.environ["foo"] = "bar" |
|
355 os.environ["{foo"] = "baz1" |
|
356 os.environ["{foo}"] = "baz2" |
|
357 self.assertEqual(posixpath.expandvars("foo"), "foo") |
|
358 self.assertEqual(posixpath.expandvars("$foo bar"), "bar bar") |
|
359 self.assertEqual(posixpath.expandvars("${foo}bar"), "barbar") |
|
360 self.assertEqual(posixpath.expandvars("$[foo]bar"), "$[foo]bar") |
|
361 self.assertEqual(posixpath.expandvars("$bar bar"), "$bar bar") |
|
362 self.assertEqual(posixpath.expandvars("$?bar"), "$?bar") |
|
363 self.assertEqual(posixpath.expandvars("${foo}bar"), "barbar") |
|
364 self.assertEqual(posixpath.expandvars("$foo}bar"), "bar}bar") |
|
365 self.assertEqual(posixpath.expandvars("${foo"), "${foo") |
|
366 self.assertEqual(posixpath.expandvars("${{foo}}"), "baz1}") |
|
367 self.assertEqual(posixpath.expandvars("$foo$foo"), "barbar") |
|
368 self.assertEqual(posixpath.expandvars("$bar$bar"), "$bar$bar") |
|
369 finally: |
|
370 os.environ.clear() |
|
371 os.environ.update(oldenv) |
|
372 |
|
373 self.assertRaises(TypeError, posixpath.expandvars) |
|
374 |
|
375 def test_normpath(self): |
|
376 self.assertEqual(posixpath.normpath(""), ".") |
|
377 self.assertEqual(posixpath.normpath("/"), "/") |
|
378 self.assertEqual(posixpath.normpath("//"), "//") |
|
379 self.assertEqual(posixpath.normpath("///"), "/") |
|
380 self.assertEqual(posixpath.normpath("///foo/.//bar//"), "/foo/bar") |
|
381 self.assertEqual(posixpath.normpath("///foo/.//bar//.//..//.//baz"), "/foo/baz") |
|
382 self.assertEqual(posixpath.normpath("///..//./foo/.//bar"), "/foo/bar") |
|
383 |
|
384 self.assertRaises(TypeError, posixpath.normpath) |
|
385 |
|
386 def test_abspath(self): |
|
387 self.assert_("foo" in posixpath.abspath("foo")) |
|
388 |
|
389 self.assertRaises(TypeError, posixpath.abspath) |
|
390 |
|
391 def test_realpath(self): |
|
392 self.assert_("foo" in realpath("foo")) |
|
393 self.assertRaises(TypeError, posixpath.realpath) |
|
394 |
|
395 if hasattr(os, "symlink"): |
|
396 def test_realpath_basic(self): |
|
397 # Basic operation. |
|
398 try: |
|
399 os.symlink(ABSTFN+"1", ABSTFN) |
|
400 self.assertEqual(realpath(ABSTFN), ABSTFN+"1") |
|
401 finally: |
|
402 test_support.unlink(ABSTFN) |
|
403 |
|
404 def test_realpath_symlink_loops(self): |
|
405 # Bug #930024, return the path unchanged if we get into an infinite |
|
406 # symlink loop. |
|
407 try: |
|
408 old_path = abspath('.') |
|
409 os.symlink(ABSTFN, ABSTFN) |
|
410 self.assertEqual(realpath(ABSTFN), ABSTFN) |
|
411 |
|
412 os.symlink(ABSTFN+"1", ABSTFN+"2") |
|
413 os.symlink(ABSTFN+"2", ABSTFN+"1") |
|
414 self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1") |
|
415 self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2") |
|
416 |
|
417 # Test using relative path as well. |
|
418 os.chdir(dirname(ABSTFN)) |
|
419 self.assertEqual(realpath(basename(ABSTFN)), ABSTFN) |
|
420 finally: |
|
421 os.chdir(old_path) |
|
422 test_support.unlink(ABSTFN) |
|
423 test_support.unlink(ABSTFN+"1") |
|
424 test_support.unlink(ABSTFN+"2") |
|
425 |
|
426 def test_realpath_resolve_parents(self): |
|
427 # We also need to resolve any symlinks in the parents of a relative |
|
428 # path passed to realpath. E.g.: current working directory is |
|
429 # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call |
|
430 # realpath("a"). This should return /usr/share/doc/a/. |
|
431 try: |
|
432 old_path = abspath('.') |
|
433 os.mkdir(ABSTFN) |
|
434 os.mkdir(ABSTFN + "/y") |
|
435 os.symlink(ABSTFN + "/y", ABSTFN + "/k") |
|
436 |
|
437 os.chdir(ABSTFN + "/k") |
|
438 self.assertEqual(realpath("a"), ABSTFN + "/y/a") |
|
439 finally: |
|
440 os.chdir(old_path) |
|
441 test_support.unlink(ABSTFN + "/k") |
|
442 safe_rmdir(ABSTFN + "/y") |
|
443 safe_rmdir(ABSTFN) |
|
444 |
|
445 def test_realpath_resolve_before_normalizing(self): |
|
446 # Bug #990669: Symbolic links should be resolved before we |
|
447 # normalize the path. E.g.: if we have directories 'a', 'k' and 'y' |
|
448 # in the following hierarchy: |
|
449 # a/k/y |
|
450 # |
|
451 # and a symbolic link 'link-y' pointing to 'y' in directory 'a', |
|
452 # then realpath("link-y/..") should return 'k', not 'a'. |
|
453 try: |
|
454 old_path = abspath('.') |
|
455 os.mkdir(ABSTFN) |
|
456 os.mkdir(ABSTFN + "/k") |
|
457 os.mkdir(ABSTFN + "/k/y") |
|
458 os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y") |
|
459 |
|
460 # Absolute path. |
|
461 self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k") |
|
462 # Relative path. |
|
463 os.chdir(dirname(ABSTFN)) |
|
464 self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."), ABSTFN + "/k") |
|
465 finally: |
|
466 os.chdir(old_path) |
|
467 test_support.unlink(ABSTFN + "/link-y") |
|
468 safe_rmdir(ABSTFN + "/k/y") |
|
469 safe_rmdir(ABSTFN + "/k") |
|
470 safe_rmdir(ABSTFN) |
|
471 |
|
472 def test_realpath_resolve_first(self): |
|
473 # Bug #1213894: The first component of the path, if not absolute, |
|
474 # must be resolved too. |
|
475 |
|
476 try: |
|
477 old_path = abspath('.') |
|
478 os.mkdir(ABSTFN) |
|
479 os.mkdir(ABSTFN + "/k") |
|
480 os.symlink(ABSTFN, ABSTFN + "link") |
|
481 os.chdir(dirname(ABSTFN)) |
|
482 |
|
483 base = basename(ABSTFN) |
|
484 self.assertEqual(realpath(base + "link"), ABSTFN) |
|
485 self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k") |
|
486 finally: |
|
487 os.chdir(old_path) |
|
488 test_support.unlink(ABSTFN + "link") |
|
489 safe_rmdir(ABSTFN + "/k") |
|
490 safe_rmdir(ABSTFN) |
|
491 |
|
492 def test_relpath(self): |
|
493 (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar") |
|
494 try: |
|
495 curdir = os.path.split(os.getcwd())[-1] |
|
496 self.assertRaises(ValueError, posixpath.relpath, "") |
|
497 self.assertEqual(posixpath.relpath("a"), "a") |
|
498 self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a") |
|
499 self.assertEqual(posixpath.relpath("a/b"), "a/b") |
|
500 self.assertEqual(posixpath.relpath("../a/b"), "../a/b") |
|
501 self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a") |
|
502 self.assertEqual(posixpath.relpath("a/b", "../c"), "../"+curdir+"/a/b") |
|
503 self.assertEqual(posixpath.relpath("a", "b/c"), "../../a") |
|
504 self.assertEqual(posixpath.relpath("a", "a"), ".") |
|
505 finally: |
|
506 os.getcwd = real_getcwd |
|
507 |
|
508 def test_main(): |
|
509 test_support.run_unittest(PosixPathTest) |
|
510 |
|
511 if __name__=="__main__": |
|
512 test_main() |