blob: d34c7e261cdd0b8cb74dc9a25db86ef59d6cb632 [file] [log] [blame]
Brett Cannonb47243a2003-06-16 21:54:50 +00001import unittest
2from test import test_support
Skip Montanaroe809b002000-07-12 00:20:08 +00003
Brett Cannonb47243a2003-06-16 21:54:50 +00004import posixpath, os
Johannes Gijsbers4ec40642004-08-14 15:01:53 +00005from posixpath import realpath, abspath, join, dirname, basename
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
10ABSTFN = abspath(test_support.TESTFN)
Skip Montanaroe809b002000-07-12 00:20:08 +000011
Brett Cannonb47243a2003-06-16 21:54:50 +000012class PosixPathTest(unittest.TestCase):
Skip Montanaroe809b002000-07-12 00:20:08 +000013
Brett Cannonb47243a2003-06-16 21:54:50 +000014 def assertIs(self, a, b):
15 self.assert_(a is b)
Skip Montanaroe809b002000-07-12 00:20:08 +000016
Brett Cannonb47243a2003-06-16 21:54:50 +000017 def test_normcase(self):
18 # Check that normcase() is idempotent
19 p = "FoO/./BaR"
20 p = posixpath.normcase(p)
21 self.assertEqual(p, posixpath.normcase(p))
Skip Montanaroe809b002000-07-12 00:20:08 +000022
Brett Cannonb47243a2003-06-16 21:54:50 +000023 self.assertRaises(TypeError, posixpath.normcase)
Skip Montanaroe809b002000-07-12 00:20:08 +000024
Brett Cannonb47243a2003-06-16 21:54:50 +000025 def test_join(self):
26 self.assertEqual(posixpath.join("/foo", "bar", "/bar", "baz"), "/bar/baz")
27 self.assertEqual(posixpath.join("/foo", "bar", "baz"), "/foo/bar/baz")
28 self.assertEqual(posixpath.join("/foo/", "bar/", "baz/"), "/foo/bar/baz/")
Skip Montanaroe809b002000-07-12 00:20:08 +000029
Brett Cannonb47243a2003-06-16 21:54:50 +000030 self.assertRaises(TypeError, posixpath.join)
Skip Montanaroe809b002000-07-12 00:20:08 +000031
Brett Cannonb47243a2003-06-16 21:54:50 +000032 def test_splitdrive(self):
33 self.assertEqual(posixpath.splitdrive("/foo/bar"), ("", "/foo/bar"))
34
35 self.assertRaises(TypeError, posixpath.splitdrive)
36
37 def test_split(self):
38 self.assertEqual(posixpath.split("/foo/bar"), ("/foo", "bar"))
39 self.assertEqual(posixpath.split("/"), ("/", ""))
40 self.assertEqual(posixpath.split("foo"), ("", "foo"))
41 self.assertEqual(posixpath.split("////foo"), ("////", "foo"))
42 self.assertEqual(posixpath.split("//foo//bar"), ("//foo", "bar"))
43
44 self.assertRaises(TypeError, posixpath.split)
45
Martin v. Löwis05c075d2007-03-07 11:04:33 +000046 def splitextTest(self, path, filename, ext):
47 self.assertEqual(posixpath.splitext(path), (filename, ext))
48 self.assertEqual(posixpath.splitext("/" + path), ("/" + filename, ext))
49 self.assertEqual(posixpath.splitext("abc/" + path), ("abc/" + filename, ext))
50 self.assertEqual(posixpath.splitext("abc.def/" + path), ("abc.def/" + filename, ext))
51 self.assertEqual(posixpath.splitext("/abc.def/" + path), ("/abc.def/" + filename, ext))
52 self.assertEqual(posixpath.splitext(path + "/"), (filename + ext + "/", ""))
Brett Cannonb47243a2003-06-16 21:54:50 +000053
Martin v. Löwis05c075d2007-03-07 11:04:33 +000054 def test_splitext(self):
55 self.splitextTest("foo.bar", "foo", ".bar")
56 self.splitextTest("foo.boo.bar", "foo.boo", ".bar")
57 self.splitextTest("foo.boo.biff.bar", "foo.boo.biff", ".bar")
58 self.splitextTest(".csh.rc", ".csh", ".rc")
59 self.splitextTest("nodots", "nodots", "")
60 self.splitextTest(".cshrc", ".cshrc", "")
61 self.splitextTest("...manydots", "...manydots", "")
62 self.splitextTest("...manydots.ext", "...manydots", ".ext")
63 self.splitextTest(".", ".", "")
64 self.splitextTest("..", "..", "")
65 self.splitextTest("........", "........", "")
66 self.splitextTest("", "", "")
Brett Cannonb47243a2003-06-16 21:54:50 +000067 self.assertRaises(TypeError, posixpath.splitext)
68
69 def test_isabs(self):
70 self.assertIs(posixpath.isabs(""), False)
71 self.assertIs(posixpath.isabs("/"), True)
72 self.assertIs(posixpath.isabs("/foo"), True)
73 self.assertIs(posixpath.isabs("/foo/bar"), True)
74 self.assertIs(posixpath.isabs("foo/bar"), False)
75
76 self.assertRaises(TypeError, posixpath.isabs)
77
78 def test_splitdrive(self):
79 self.assertEqual(posixpath.splitdrive("/foo/bar"), ("", "/foo/bar"))
80
81 self.assertRaises(TypeError, posixpath.splitdrive)
82
83 def test_basename(self):
84 self.assertEqual(posixpath.basename("/foo/bar"), "bar")
85 self.assertEqual(posixpath.basename("/"), "")
86 self.assertEqual(posixpath.basename("foo"), "foo")
87 self.assertEqual(posixpath.basename("////foo"), "foo")
88 self.assertEqual(posixpath.basename("//foo//bar"), "bar")
89
90 self.assertRaises(TypeError, posixpath.basename)
91
92 def test_dirname(self):
93 self.assertEqual(posixpath.dirname("/foo/bar"), "/foo")
94 self.assertEqual(posixpath.dirname("/"), "/")
95 self.assertEqual(posixpath.dirname("foo"), "")
96 self.assertEqual(posixpath.dirname("////foo"), "////")
97 self.assertEqual(posixpath.dirname("//foo//bar"), "//foo")
98
99 self.assertRaises(TypeError, posixpath.dirname)
100
101 def test_commonprefix(self):
102 self.assertEqual(
103 posixpath.commonprefix([]),
104 ""
105 )
106 self.assertEqual(
107 posixpath.commonprefix(["/home/swenson/spam", "/home/swen/spam"]),
108 "/home/swen"
109 )
110 self.assertEqual(
111 posixpath.commonprefix(["/home/swen/spam", "/home/swen/eggs"]),
112 "/home/swen/"
113 )
114 self.assertEqual(
115 posixpath.commonprefix(["/home/swen/spam", "/home/swen/spam"]),
116 "/home/swen/spam"
117 )
118
119 def test_getsize(self):
120 f = open(test_support.TESTFN, "wb")
121 try:
122 f.write("foo")
123 f.close()
124 self.assertEqual(posixpath.getsize(test_support.TESTFN), 3)
125 finally:
126 if not f.closed:
127 f.close()
128 os.remove(test_support.TESTFN)
129
130 def test_time(self):
131 f = open(test_support.TESTFN, "wb")
132 try:
133 f.write("foo")
134 f.close()
135 f = open(test_support.TESTFN, "ab")
136 f.write("bar")
137 f.close()
138 f = open(test_support.TESTFN, "rb")
139 d = f.read()
140 f.close()
141 self.assertEqual(d, "foobar")
142
143 self.assert_(
144 posixpath.getctime(test_support.TESTFN) <=
145 posixpath.getmtime(test_support.TESTFN)
146 )
147 finally:
148 if not f.closed:
149 f.close()
150 os.remove(test_support.TESTFN)
151
152 def test_islink(self):
153 self.assertIs(posixpath.islink(test_support.TESTFN + "1"), False)
154 f = open(test_support.TESTFN + "1", "wb")
155 try:
156 f.write("foo")
157 f.close()
158 self.assertIs(posixpath.islink(test_support.TESTFN + "1"), False)
159 if hasattr(os, "symlink"):
160 os.symlink(test_support.TESTFN + "1", test_support.TESTFN + "2")
161 self.assertIs(posixpath.islink(test_support.TESTFN + "2"), True)
162 os.remove(test_support.TESTFN + "1")
163 self.assertIs(posixpath.islink(test_support.TESTFN + "2"), True)
164 self.assertIs(posixpath.exists(test_support.TESTFN + "2"), False)
Johannes Gijsbersae882f72004-08-30 10:19:56 +0000165 self.assertIs(posixpath.lexists(test_support.TESTFN + "2"), True)
Brett Cannonb47243a2003-06-16 21:54:50 +0000166 finally:
167 if not f.close():
168 f.close()
169 try:
170 os.remove(test_support.TESTFN + "1")
171 except os.error:
172 pass
173 try:
174 os.remove(test_support.TESTFN + "2")
175 except os.error:
176 pass
177
178 self.assertRaises(TypeError, posixpath.islink)
179
180 def test_exists(self):
181 self.assertIs(posixpath.exists(test_support.TESTFN), False)
182 f = open(test_support.TESTFN, "wb")
183 try:
184 f.write("foo")
185 f.close()
186 self.assertIs(posixpath.exists(test_support.TESTFN), True)
Johannes Gijsbersae882f72004-08-30 10:19:56 +0000187 self.assertIs(posixpath.lexists(test_support.TESTFN), True)
Brett Cannonb47243a2003-06-16 21:54:50 +0000188 finally:
189 if not f.close():
190 f.close()
191 try:
192 os.remove(test_support.TESTFN)
193 except os.error:
194 pass
195
196 self.assertRaises(TypeError, posixpath.exists)
197
198 def test_isdir(self):
199 self.assertIs(posixpath.isdir(test_support.TESTFN), False)
200 f = open(test_support.TESTFN, "wb")
201 try:
202 f.write("foo")
203 f.close()
204 self.assertIs(posixpath.isdir(test_support.TESTFN), False)
205 os.remove(test_support.TESTFN)
206 os.mkdir(test_support.TESTFN)
207 self.assertIs(posixpath.isdir(test_support.TESTFN), True)
208 os.rmdir(test_support.TESTFN)
209 finally:
210 if not f.close():
211 f.close()
212 try:
213 os.remove(test_support.TESTFN)
214 except os.error:
215 pass
216 try:
217 os.rmdir(test_support.TESTFN)
218 except os.error:
219 pass
220
221 self.assertRaises(TypeError, posixpath.isdir)
222
223 def test_isfile(self):
224 self.assertIs(posixpath.isfile(test_support.TESTFN), False)
225 f = open(test_support.TESTFN, "wb")
226 try:
227 f.write("foo")
228 f.close()
229 self.assertIs(posixpath.isfile(test_support.TESTFN), True)
230 os.remove(test_support.TESTFN)
231 os.mkdir(test_support.TESTFN)
232 self.assertIs(posixpath.isfile(test_support.TESTFN), False)
233 os.rmdir(test_support.TESTFN)
234 finally:
235 if not f.close():
236 f.close()
237 try:
238 os.remove(test_support.TESTFN)
239 except os.error:
240 pass
241 try:
242 os.rmdir(test_support.TESTFN)
243 except os.error:
244 pass
245
246 self.assertRaises(TypeError, posixpath.isdir)
247
248 def test_samefile(self):
249 f = open(test_support.TESTFN + "1", "wb")
250 try:
251 f.write("foo")
252 f.close()
253 self.assertIs(
254 posixpath.samefile(
255 test_support.TESTFN + "1",
256 test_support.TESTFN + "1"
257 ),
258 True
259 )
Tim Peters478c1052003-06-29 05:46:54 +0000260 # If we don't have links, assume that os.stat doesn't return resonable
Brett Cannonb47243a2003-06-16 21:54:50 +0000261 # inode information and thus, that samefile() doesn't work
262 if hasattr(os, "symlink"):
263 os.symlink(
264 test_support.TESTFN + "1",
265 test_support.TESTFN + "2"
266 )
267 self.assertIs(
268 posixpath.samefile(
269 test_support.TESTFN + "1",
270 test_support.TESTFN + "2"
271 ),
272 True
273 )
274 os.remove(test_support.TESTFN + "2")
275 f = open(test_support.TESTFN + "2", "wb")
276 f.write("bar")
277 f.close()
278 self.assertIs(
279 posixpath.samefile(
280 test_support.TESTFN + "1",
281 test_support.TESTFN + "2"
282 ),
283 False
284 )
285 finally:
286 if not f.close():
287 f.close()
288 try:
289 os.remove(test_support.TESTFN + "1")
290 except os.error:
291 pass
292 try:
293 os.remove(test_support.TESTFN + "2")
294 except os.error:
295 pass
296
297 self.assertRaises(TypeError, posixpath.samefile)
298
299 def test_samestat(self):
300 f = open(test_support.TESTFN + "1", "wb")
301 try:
302 f.write("foo")
303 f.close()
304 self.assertIs(
305 posixpath.samestat(
306 os.stat(test_support.TESTFN + "1"),
307 os.stat(test_support.TESTFN + "1")
308 ),
309 True
310 )
Tim Peters478c1052003-06-29 05:46:54 +0000311 # If we don't have links, assume that os.stat() doesn't return resonable
Brett Cannonb47243a2003-06-16 21:54:50 +0000312 # inode information and thus, that samefile() doesn't work
313 if hasattr(os, "symlink"):
314 if hasattr(os, "symlink"):
315 os.symlink(test_support.TESTFN + "1", test_support.TESTFN + "2")
316 self.assertIs(
317 posixpath.samestat(
318 os.stat(test_support.TESTFN + "1"),
319 os.stat(test_support.TESTFN + "2")
320 ),
321 True
322 )
323 os.remove(test_support.TESTFN + "2")
324 f = open(test_support.TESTFN + "2", "wb")
325 f.write("bar")
326 f.close()
327 self.assertIs(
328 posixpath.samestat(
329 os.stat(test_support.TESTFN + "1"),
330 os.stat(test_support.TESTFN + "2")
331 ),
332 False
333 )
334 finally:
335 if not f.close():
336 f.close()
337 try:
338 os.remove(test_support.TESTFN + "1")
339 except os.error:
340 pass
341 try:
342 os.remove(test_support.TESTFN + "2")
343 except os.error:
344 pass
345
346 self.assertRaises(TypeError, posixpath.samestat)
347
348 def test_ismount(self):
349 self.assertIs(posixpath.ismount("/"), True)
350
351 self.assertRaises(TypeError, posixpath.ismount)
352
353 def test_expanduser(self):
354 self.assertEqual(posixpath.expanduser("foo"), "foo")
Brett Cannonb47243a2003-06-16 21:54:50 +0000355 try:
356 import pwd
357 except ImportError:
358 pass
359 else:
Walter Dörwalda9da5ae2003-06-19 10:21:14 +0000360 self.assert_(isinstance(posixpath.expanduser("~/"), basestring))
Neal Norwitz168e73d2003-07-01 03:33:31 +0000361 # if home directory == root directory, this test makes no sense
362 if posixpath.expanduser("~") != '/':
363 self.assertEqual(
364 posixpath.expanduser("~") + "/",
365 posixpath.expanduser("~/")
366 )
Brett Cannonb47243a2003-06-16 21:54:50 +0000367 self.assert_(isinstance(posixpath.expanduser("~root/"), basestring))
368 self.assert_(isinstance(posixpath.expanduser("~foo/"), basestring))
369
370 self.assertRaises(TypeError, posixpath.expanduser)
371
372 def test_expandvars(self):
373 oldenv = os.environ.copy()
374 try:
375 os.environ.clear()
376 os.environ["foo"] = "bar"
377 os.environ["{foo"] = "baz1"
378 os.environ["{foo}"] = "baz2"
379 self.assertEqual(posixpath.expandvars("foo"), "foo")
380 self.assertEqual(posixpath.expandvars("$foo bar"), "bar bar")
381 self.assertEqual(posixpath.expandvars("${foo}bar"), "barbar")
382 self.assertEqual(posixpath.expandvars("$[foo]bar"), "$[foo]bar")
383 self.assertEqual(posixpath.expandvars("$bar bar"), "$bar bar")
384 self.assertEqual(posixpath.expandvars("$?bar"), "$?bar")
385 self.assertEqual(posixpath.expandvars("${foo}bar"), "barbar")
386 self.assertEqual(posixpath.expandvars("$foo}bar"), "bar}bar")
387 self.assertEqual(posixpath.expandvars("${foo"), "${foo")
388 self.assertEqual(posixpath.expandvars("${{foo}}"), "baz1}")
Sjoerd Mullender33a0a062007-01-16 16:42:38 +0000389 self.assertEqual(posixpath.expandvars("$foo$foo"), "barbar")
390 self.assertEqual(posixpath.expandvars("$bar$bar"), "$bar$bar")
Brett Cannonb47243a2003-06-16 21:54:50 +0000391 finally:
392 os.environ.clear()
393 os.environ.update(oldenv)
394
395 self.assertRaises(TypeError, posixpath.expandvars)
396
397 def test_normpath(self):
398 self.assertEqual(posixpath.normpath(""), ".")
399 self.assertEqual(posixpath.normpath("/"), "/")
400 self.assertEqual(posixpath.normpath("//"), "//")
401 self.assertEqual(posixpath.normpath("///"), "/")
402 self.assertEqual(posixpath.normpath("///foo/.//bar//"), "/foo/bar")
403 self.assertEqual(posixpath.normpath("///foo/.//bar//.//..//.//baz"), "/foo/baz")
404 self.assertEqual(posixpath.normpath("///..//./foo/.//bar"), "/foo/bar")
405
406 self.assertRaises(TypeError, posixpath.normpath)
407
408 def test_abspath(self):
409 self.assert_("foo" in posixpath.abspath("foo"))
410
411 self.assertRaises(TypeError, posixpath.abspath)
412
413 def test_realpath(self):
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000414 self.assert_("foo" in realpath("foo"))
Brett Cannonb47243a2003-06-16 21:54:50 +0000415 self.assertRaises(TypeError, posixpath.realpath)
Tim Petersa45cacf2004-08-20 03:47:14 +0000416
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000417 if hasattr(os, "symlink"):
418 def test_realpath_basic(self):
419 # Basic operation.
420 try:
421 os.symlink(ABSTFN+"1", ABSTFN)
422 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
423 finally:
424 self.safe_remove(ABSTFN)
Tim Petersa45cacf2004-08-20 03:47:14 +0000425
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000426 def test_realpath_symlink_loops(self):
427 # Bug #930024, return the path unchanged if we get into an infinite
428 # symlink loop.
429 try:
430 old_path = abspath('.')
431 os.symlink(ABSTFN, ABSTFN)
432 self.assertEqual(realpath(ABSTFN), ABSTFN)
433
434 os.symlink(ABSTFN+"1", ABSTFN+"2")
435 os.symlink(ABSTFN+"2", ABSTFN+"1")
436 self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1")
437 self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2")
438
439 # Test using relative path as well.
440 os.chdir(dirname(ABSTFN))
441 self.assertEqual(realpath(basename(ABSTFN)), ABSTFN)
442 finally:
443 os.chdir(old_path)
444 self.safe_remove(ABSTFN)
445 self.safe_remove(ABSTFN+"1")
446 self.safe_remove(ABSTFN+"2")
447
Tim Petersa45cacf2004-08-20 03:47:14 +0000448 def test_realpath_resolve_parents(self):
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000449 # We also need to resolve any symlinks in the parents of a relative
450 # path passed to realpath. E.g.: current working directory is
451 # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call
452 # realpath("a"). This should return /usr/share/doc/a/.
453 try:
454 old_path = abspath('.')
455 os.mkdir(ABSTFN)
456 os.mkdir(ABSTFN + "/y")
457 os.symlink(ABSTFN + "/y", ABSTFN + "/k")
458
459 os.chdir(ABSTFN + "/k")
460 self.assertEqual(realpath("a"), ABSTFN + "/y/a")
461 finally:
462 os.chdir(old_path)
463 self.safe_remove(ABSTFN + "/k")
464 self.safe_rmdir(ABSTFN + "/y")
465 self.safe_rmdir(ABSTFN)
466
467 def test_realpath_resolve_before_normalizing(self):
468 # Bug #990669: Symbolic links should be resolved before we
469 # normalize the path. E.g.: if we have directories 'a', 'k' and 'y'
470 # in the following hierarchy:
471 # a/k/y
472 #
473 # and a symbolic link 'link-y' pointing to 'y' in directory 'a',
474 # then realpath("link-y/..") should return 'k', not 'a'.
475 try:
476 old_path = abspath('.')
477 os.mkdir(ABSTFN)
478 os.mkdir(ABSTFN + "/k")
479 os.mkdir(ABSTFN + "/k/y")
480 os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y")
481
482 # Absolute path.
483 self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k")
484 # Relative path.
485 os.chdir(dirname(ABSTFN))
486 self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."), ABSTFN + "/k")
487 finally:
488 os.chdir(old_path)
489 self.safe_remove(ABSTFN + "/link-y")
490 self.safe_rmdir(ABSTFN + "/k/y")
491 self.safe_rmdir(ABSTFN + "/k")
492 self.safe_rmdir(ABSTFN)
Tim Peters5d36a552005-06-03 22:40:27 +0000493
Georg Brandl268e61c2005-06-03 14:28:50 +0000494 def test_realpath_resolve_first(self):
495 # Bug #1213894: The first component of the path, if not absolute,
496 # must be resolved too.
497
498 try:
499 old_path = abspath('.')
500 os.mkdir(ABSTFN)
501 os.mkdir(ABSTFN + "/k")
502 os.symlink(ABSTFN, ABSTFN + "link")
503 os.chdir(dirname(ABSTFN))
Tim Peters5d36a552005-06-03 22:40:27 +0000504
Georg Brandl268e61c2005-06-03 14:28:50 +0000505 base = basename(ABSTFN)
506 self.assertEqual(realpath(base + "link"), ABSTFN)
507 self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k")
508 finally:
509 os.chdir(old_path)
510 self.safe_remove(ABSTFN + "link")
511 self.safe_rmdir(ABSTFN + "/k")
512 self.safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000513
514 # Convenience functions for removing temporary files.
515 def pass_os_error(self, func, filename):
516 try: func(filename)
517 except OSError: pass
518
519 def safe_remove(self, filename):
520 self.pass_os_error(os.remove, filename)
521
522 def safe_rmdir(self, dirname):
523 self.pass_os_error(os.rmdir, dirname)
Brett Cannonb47243a2003-06-16 21:54:50 +0000524
525def test_main():
526 test_support.run_unittest(PosixPathTest)
527
528if __name__=="__main__":
529 test_main()