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