blob: ec2fbaee322dbe0e476f51817f1842384e324943 [file] [log] [blame]
Hynek Schlawackc5a45662012-07-17 13:05:43 +02001import itertools
Brian Curtind40e6f72010-07-08 21:39:08 +00002import os
Victor Stinner1ab6c2d2011-11-15 22:27:41 +01003import posixpath
Brian Curtind40e6f72010-07-08 21:39:08 +00004import sys
Victor Stinner1ab6c2d2011-11-15 22:27:41 +01005import unittest
6import warnings
Georg Brandl89fad142010-03-14 10:23:39 +00007from posixpath import realpath, abspath, dirname, basename
Victor Stinner1ab6c2d2011-11-15 22:27:41 +01008from test import support, test_genericpath
Johannes Gijsbers4ec40642004-08-14 15:01:53 +00009
Michael Foord07926f02011-03-16 17:19:16 -040010try:
11 import posix
12except ImportError:
13 posix = None
14
Johannes Gijsbers4ec40642004-08-14 15:01:53 +000015# An absolute path to a temporary filename for testing. We can't rely on TESTFN
16# being an absolute path, so we need this.
17
Benjamin Petersonee8712c2008-05-20 21:35:26 +000018ABSTFN = abspath(support.TESTFN)
Skip Montanaroe809b002000-07-12 00:20:08 +000019
Brian Curtind40e6f72010-07-08 21:39:08 +000020def skip_if_ABSTFN_contains_backslash(test):
21 """
22 On Windows, posixpath.abspath still returns paths with backslashes
23 instead of posix forward slashes. If this is the case, several tests
24 fail, so skip them.
25 """
26 found_backslash = '\\' in ABSTFN
27 msg = "ABSTFN is not a posix path - tests fail"
28 return [test, unittest.skip(msg)(test)][found_backslash]
29
Guido van Rossumd8faa362007-04-27 19:54:29 +000030def safe_rmdir(dirname):
31 try:
32 os.rmdir(dirname)
33 except OSError:
34 pass
35
Brett Cannonb47243a2003-06-16 21:54:50 +000036class PosixPathTest(unittest.TestCase):
Skip Montanaroe809b002000-07-12 00:20:08 +000037
Guido van Rossumd8faa362007-04-27 19:54:29 +000038 def setUp(self):
39 self.tearDown()
40
41 def tearDown(self):
42 for suffix in ["", "1", "2"]:
Benjamin Petersonee8712c2008-05-20 21:35:26 +000043 support.unlink(support.TESTFN + suffix)
44 safe_rmdir(support.TESTFN + suffix)
Guido van Rossumd8faa362007-04-27 19:54:29 +000045
Brett Cannonb47243a2003-06-16 21:54:50 +000046 def test_join(self):
Guido van Rossumf0af3e32008-10-02 18:55:37 +000047 self.assertEqual(posixpath.join("/foo", "bar", "/bar", "baz"),
48 "/bar/baz")
Brett Cannonb47243a2003-06-16 21:54:50 +000049 self.assertEqual(posixpath.join("/foo", "bar", "baz"), "/foo/bar/baz")
Guido van Rossumf0af3e32008-10-02 18:55:37 +000050 self.assertEqual(posixpath.join("/foo/", "bar/", "baz/"),
51 "/foo/bar/baz/")
52
53 self.assertEqual(posixpath.join(b"/foo", b"bar", b"/bar", b"baz"),
54 b"/bar/baz")
55 self.assertEqual(posixpath.join(b"/foo", b"bar", b"baz"),
56 b"/foo/bar/baz")
57 self.assertEqual(posixpath.join(b"/foo/", b"bar/", b"baz/"),
58 b"/foo/bar/baz/")
Skip Montanaroe809b002000-07-12 00:20:08 +000059
Serhiy Storchaka549c1972014-08-24 12:18:09 +030060 def test_join_errors(self):
61 # Check posixpath.join raises friendly TypeErrors.
62 errmsg = "Can't mix strings and bytes in path components"
63 with self.assertRaisesRegex(TypeError, errmsg):
64 posixpath.join(b'bytes', 'str')
65 with self.assertRaisesRegex(TypeError, errmsg):
66 posixpath.join('str', b'bytes')
Hynek Schlawackc5a45662012-07-17 13:05:43 +020067 # regression, see #15377
68 with self.assertRaises(TypeError) as cm:
Hynek Schlawack0b350c62012-07-17 14:28:44 +020069 posixpath.join(None, 'str')
Serhiy Storchaka549c1972014-08-24 12:18:09 +030070 self.assertNotEqual(cm.exception.args[0], errmsg)
Skip Montanaroe809b002000-07-12 00:20:08 +000071
Brett Cannonb47243a2003-06-16 21:54:50 +000072 def test_split(self):
73 self.assertEqual(posixpath.split("/foo/bar"), ("/foo", "bar"))
74 self.assertEqual(posixpath.split("/"), ("/", ""))
75 self.assertEqual(posixpath.split("foo"), ("", "foo"))
76 self.assertEqual(posixpath.split("////foo"), ("////", "foo"))
77 self.assertEqual(posixpath.split("//foo//bar"), ("//foo", "bar"))
78
Guido van Rossumf0af3e32008-10-02 18:55:37 +000079 self.assertEqual(posixpath.split(b"/foo/bar"), (b"/foo", b"bar"))
80 self.assertEqual(posixpath.split(b"/"), (b"/", b""))
81 self.assertEqual(posixpath.split(b"foo"), (b"", b"foo"))
82 self.assertEqual(posixpath.split(b"////foo"), (b"////", b"foo"))
83 self.assertEqual(posixpath.split(b"//foo//bar"), (b"//foo", b"bar"))
84
Guido van Rossumd8faa362007-04-27 19:54:29 +000085 def splitextTest(self, path, filename, ext):
86 self.assertEqual(posixpath.splitext(path), (filename, ext))
87 self.assertEqual(posixpath.splitext("/" + path), ("/" + filename, ext))
Guido van Rossumf0af3e32008-10-02 18:55:37 +000088 self.assertEqual(posixpath.splitext("abc/" + path),
89 ("abc/" + filename, ext))
90 self.assertEqual(posixpath.splitext("abc.def/" + path),
91 ("abc.def/" + filename, ext))
92 self.assertEqual(posixpath.splitext("/abc.def/" + path),
93 ("/abc.def/" + filename, ext))
94 self.assertEqual(posixpath.splitext(path + "/"),
95 (filename + ext + "/", ""))
96
97 path = bytes(path, "ASCII")
98 filename = bytes(filename, "ASCII")
99 ext = bytes(ext, "ASCII")
100
101 self.assertEqual(posixpath.splitext(path), (filename, ext))
102 self.assertEqual(posixpath.splitext(b"/" + path),
103 (b"/" + filename, ext))
104 self.assertEqual(posixpath.splitext(b"abc/" + path),
105 (b"abc/" + filename, ext))
106 self.assertEqual(posixpath.splitext(b"abc.def/" + path),
107 (b"abc.def/" + filename, ext))
108 self.assertEqual(posixpath.splitext(b"/abc.def/" + path),
109 (b"/abc.def/" + filename, ext))
110 self.assertEqual(posixpath.splitext(path + b"/"),
111 (filename + ext + b"/", b""))
Brett Cannonb47243a2003-06-16 21:54:50 +0000112
Guido van Rossumd8faa362007-04-27 19:54:29 +0000113 def test_splitext(self):
114 self.splitextTest("foo.bar", "foo", ".bar")
115 self.splitextTest("foo.boo.bar", "foo.boo", ".bar")
116 self.splitextTest("foo.boo.biff.bar", "foo.boo.biff", ".bar")
117 self.splitextTest(".csh.rc", ".csh", ".rc")
118 self.splitextTest("nodots", "nodots", "")
119 self.splitextTest(".cshrc", ".cshrc", "")
120 self.splitextTest("...manydots", "...manydots", "")
121 self.splitextTest("...manydots.ext", "...manydots", ".ext")
122 self.splitextTest(".", ".", "")
123 self.splitextTest("..", "..", "")
124 self.splitextTest("........", "........", "")
125 self.splitextTest("", "", "")
Brett Cannonb47243a2003-06-16 21:54:50 +0000126
127 def test_isabs(self):
128 self.assertIs(posixpath.isabs(""), False)
129 self.assertIs(posixpath.isabs("/"), True)
130 self.assertIs(posixpath.isabs("/foo"), True)
131 self.assertIs(posixpath.isabs("/foo/bar"), True)
132 self.assertIs(posixpath.isabs("foo/bar"), False)
133
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000134 self.assertIs(posixpath.isabs(b""), False)
135 self.assertIs(posixpath.isabs(b"/"), True)
136 self.assertIs(posixpath.isabs(b"/foo"), True)
137 self.assertIs(posixpath.isabs(b"/foo/bar"), True)
138 self.assertIs(posixpath.isabs(b"foo/bar"), False)
139
Brett Cannonb47243a2003-06-16 21:54:50 +0000140 def test_basename(self):
141 self.assertEqual(posixpath.basename("/foo/bar"), "bar")
142 self.assertEqual(posixpath.basename("/"), "")
143 self.assertEqual(posixpath.basename("foo"), "foo")
144 self.assertEqual(posixpath.basename("////foo"), "foo")
145 self.assertEqual(posixpath.basename("//foo//bar"), "bar")
146
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000147 self.assertEqual(posixpath.basename(b"/foo/bar"), b"bar")
148 self.assertEqual(posixpath.basename(b"/"), b"")
149 self.assertEqual(posixpath.basename(b"foo"), b"foo")
150 self.assertEqual(posixpath.basename(b"////foo"), b"foo")
151 self.assertEqual(posixpath.basename(b"//foo//bar"), b"bar")
152
Brett Cannonb47243a2003-06-16 21:54:50 +0000153 def test_dirname(self):
154 self.assertEqual(posixpath.dirname("/foo/bar"), "/foo")
155 self.assertEqual(posixpath.dirname("/"), "/")
156 self.assertEqual(posixpath.dirname("foo"), "")
157 self.assertEqual(posixpath.dirname("////foo"), "////")
158 self.assertEqual(posixpath.dirname("//foo//bar"), "//foo")
159
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000160 self.assertEqual(posixpath.dirname(b"/foo/bar"), b"/foo")
161 self.assertEqual(posixpath.dirname(b"/"), b"/")
162 self.assertEqual(posixpath.dirname(b"foo"), b"")
163 self.assertEqual(posixpath.dirname(b"////foo"), b"////")
164 self.assertEqual(posixpath.dirname(b"//foo//bar"), b"//foo")
165
Brett Cannonb47243a2003-06-16 21:54:50 +0000166 def test_islink(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000167 self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
Michael Foord07926f02011-03-16 17:19:16 -0400168 self.assertIs(posixpath.lexists(support.TESTFN + "2"), False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000169 f = open(support.TESTFN + "1", "wb")
Brett Cannonb47243a2003-06-16 21:54:50 +0000170 try:
Guido van Rossum7dcb8442007-08-27 23:26:56 +0000171 f.write(b"foo")
Brett Cannonb47243a2003-06-16 21:54:50 +0000172 f.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000173 self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
Brian Curtin3b4499c2010-12-28 14:31:47 +0000174 if support.can_symlink():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000175 os.symlink(support.TESTFN + "1", support.TESTFN + "2")
176 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
177 os.remove(support.TESTFN + "1")
178 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
179 self.assertIs(posixpath.exists(support.TESTFN + "2"), False)
180 self.assertIs(posixpath.lexists(support.TESTFN + "2"), True)
Brett Cannonb47243a2003-06-16 21:54:50 +0000181 finally:
182 if not f.close():
183 f.close()
Brett Cannonb47243a2003-06-16 21:54:50 +0000184
Brett Cannonb47243a2003-06-16 21:54:50 +0000185 def test_ismount(self):
186 self.assertIs(posixpath.ismount("/"), True)
Victor Stinner1ab6c2d2011-11-15 22:27:41 +0100187 with warnings.catch_warnings():
188 warnings.simplefilter("ignore", DeprecationWarning)
189 self.assertIs(posixpath.ismount(b"/"), True)
Michael Foord07926f02011-03-16 17:19:16 -0400190
191 def test_ismount_non_existent(self):
192 # Non-existent mountpoint.
193 self.assertIs(posixpath.ismount(ABSTFN), False)
194 try:
195 os.mkdir(ABSTFN)
196 self.assertIs(posixpath.ismount(ABSTFN), False)
197 finally:
198 safe_rmdir(ABSTFN)
199
200 @unittest.skipUnless(support.can_symlink(),
201 "Test requires symlink support")
202 def test_ismount_symlinks(self):
203 # Symlinks are never mountpoints.
204 try:
205 os.symlink("/", ABSTFN)
206 self.assertIs(posixpath.ismount(ABSTFN), False)
207 finally:
208 os.unlink(ABSTFN)
209
210 @unittest.skipIf(posix is None, "Test requires posix module")
211 def test_ismount_different_device(self):
212 # Simulate the path being on a different device from its parent by
213 # mocking out st_dev.
214 save_lstat = os.lstat
215 def fake_lstat(path):
216 st_ino = 0
217 st_dev = 0
218 if path == ABSTFN:
219 st_dev = 1
220 st_ino = 1
221 return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
222 try:
223 os.lstat = fake_lstat
224 self.assertIs(posixpath.ismount(ABSTFN), True)
225 finally:
226 os.lstat = save_lstat
Brett Cannonb47243a2003-06-16 21:54:50 +0000227
Brett Cannonb47243a2003-06-16 21:54:50 +0000228 def test_expanduser(self):
229 self.assertEqual(posixpath.expanduser("foo"), "foo")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000230 self.assertEqual(posixpath.expanduser(b"foo"), b"foo")
Brett Cannonb47243a2003-06-16 21:54:50 +0000231 try:
232 import pwd
233 except ImportError:
234 pass
235 else:
Ezio Melottie9615932010-01-24 19:26:24 +0000236 self.assertIsInstance(posixpath.expanduser("~/"), str)
237 self.assertIsInstance(posixpath.expanduser(b"~/"), bytes)
Neal Norwitz168e73d2003-07-01 03:33:31 +0000238 # if home directory == root directory, this test makes no sense
239 if posixpath.expanduser("~") != '/':
240 self.assertEqual(
241 posixpath.expanduser("~") + "/",
242 posixpath.expanduser("~/")
243 )
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000244 self.assertEqual(
245 posixpath.expanduser(b"~") + b"/",
246 posixpath.expanduser(b"~/")
247 )
Ezio Melottie9615932010-01-24 19:26:24 +0000248 self.assertIsInstance(posixpath.expanduser("~root/"), str)
249 self.assertIsInstance(posixpath.expanduser("~foo/"), str)
250 self.assertIsInstance(posixpath.expanduser(b"~root/"), bytes)
251 self.assertIsInstance(posixpath.expanduser(b"~foo/"), bytes)
Brett Cannonb47243a2003-06-16 21:54:50 +0000252
Hirokazu Yamamoto71959632009-04-27 01:44:28 +0000253 with support.EnvironmentVarGuard() as env:
Walter Dörwald155374d2009-05-01 19:58:58 +0000254 env['HOME'] = '/'
Walter Dörwaldb525e182009-04-26 21:39:21 +0000255 self.assertEqual(posixpath.expanduser("~"), "/")
Jesus Cea7f0d8882012-05-10 05:10:50 +0200256 self.assertEqual(posixpath.expanduser("~/foo"), "/foo")
Michael Foord07926f02011-03-16 17:19:16 -0400257 # expanduser should fall back to using the password database
258 del env['HOME']
259 home = pwd.getpwuid(os.getuid()).pw_dir
Ezio Melottice82d572013-05-09 15:19:45 +0300260 # $HOME can end with a trailing /, so strip it (see #17809)
261 self.assertEqual(posixpath.expanduser("~"), home.rstrip("/"))
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000262
Brett Cannonb47243a2003-06-16 21:54:50 +0000263 def test_normpath(self):
264 self.assertEqual(posixpath.normpath(""), ".")
265 self.assertEqual(posixpath.normpath("/"), "/")
266 self.assertEqual(posixpath.normpath("//"), "//")
267 self.assertEqual(posixpath.normpath("///"), "/")
268 self.assertEqual(posixpath.normpath("///foo/.//bar//"), "/foo/bar")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000269 self.assertEqual(posixpath.normpath("///foo/.//bar//.//..//.//baz"),
270 "/foo/baz")
Brett Cannonb47243a2003-06-16 21:54:50 +0000271 self.assertEqual(posixpath.normpath("///..//./foo/.//bar"), "/foo/bar")
272
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000273 self.assertEqual(posixpath.normpath(b""), b".")
274 self.assertEqual(posixpath.normpath(b"/"), b"/")
275 self.assertEqual(posixpath.normpath(b"//"), b"//")
276 self.assertEqual(posixpath.normpath(b"///"), b"/")
277 self.assertEqual(posixpath.normpath(b"///foo/.//bar//"), b"/foo/bar")
278 self.assertEqual(posixpath.normpath(b"///foo/.//bar//.//..//.//baz"),
279 b"/foo/baz")
280 self.assertEqual(posixpath.normpath(b"///..//./foo/.//bar"),
281 b"/foo/bar")
282
Serhiy Storchaka1548ed62013-02-18 13:32:30 +0200283 @skip_if_ABSTFN_contains_backslash
Serhiy Storchaka467393d2013-02-18 12:21:04 +0200284 def test_realpath_curdir(self):
285 self.assertEqual(realpath('.'), os.getcwd())
286 self.assertEqual(realpath('./.'), os.getcwd())
287 self.assertEqual(realpath('/'.join(['.'] * 100)), os.getcwd())
288
289 self.assertEqual(realpath(b'.'), os.getcwdb())
290 self.assertEqual(realpath(b'./.'), os.getcwdb())
291 self.assertEqual(realpath(b'/'.join([b'.'] * 100)), os.getcwdb())
292
Serhiy Storchaka1548ed62013-02-18 13:32:30 +0200293 @skip_if_ABSTFN_contains_backslash
Serhiy Storchaka467393d2013-02-18 12:21:04 +0200294 def test_realpath_pardir(self):
295 self.assertEqual(realpath('..'), dirname(os.getcwd()))
296 self.assertEqual(realpath('../..'), dirname(dirname(os.getcwd())))
297 self.assertEqual(realpath('/'.join(['..'] * 100)), '/')
298
299 self.assertEqual(realpath(b'..'), dirname(os.getcwdb()))
300 self.assertEqual(realpath(b'../..'), dirname(dirname(os.getcwdb())))
301 self.assertEqual(realpath(b'/'.join([b'..'] * 100)), b'/')
302
Brian Curtin52173d42010-12-02 18:29:18 +0000303 @unittest.skipUnless(hasattr(os, "symlink"),
304 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000305 @skip_if_ABSTFN_contains_backslash
306 def test_realpath_basic(self):
307 # Basic operation.
308 try:
309 os.symlink(ABSTFN+"1", ABSTFN)
310 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
311 finally:
312 support.unlink(ABSTFN)
Tim Petersa45cacf2004-08-20 03:47:14 +0000313
Brian Curtin52173d42010-12-02 18:29:18 +0000314 @unittest.skipUnless(hasattr(os, "symlink"),
315 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000316 @skip_if_ABSTFN_contains_backslash
Michael Foord07926f02011-03-16 17:19:16 -0400317 def test_realpath_relative(self):
318 try:
319 os.symlink(posixpath.relpath(ABSTFN+"1"), ABSTFN)
320 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
321 finally:
322 support.unlink(ABSTFN)
323
324 @unittest.skipUnless(hasattr(os, "symlink"),
325 "Missing symlink implementation")
326 @skip_if_ABSTFN_contains_backslash
Brian Curtind40e6f72010-07-08 21:39:08 +0000327 def test_realpath_symlink_loops(self):
328 # Bug #930024, return the path unchanged if we get into an infinite
329 # symlink loop.
330 try:
331 old_path = abspath('.')
332 os.symlink(ABSTFN, ABSTFN)
333 self.assertEqual(realpath(ABSTFN), ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000334
Brian Curtind40e6f72010-07-08 21:39:08 +0000335 os.symlink(ABSTFN+"1", ABSTFN+"2")
336 os.symlink(ABSTFN+"2", ABSTFN+"1")
337 self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1")
338 self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000339
Serhiy Storchakadf326912013-02-10 12:22:07 +0200340 self.assertEqual(realpath(ABSTFN+"1/x"), ABSTFN+"1/x")
341 self.assertEqual(realpath(ABSTFN+"1/.."), dirname(ABSTFN))
342 self.assertEqual(realpath(ABSTFN+"1/../x"), dirname(ABSTFN) + "/x")
343 os.symlink(ABSTFN+"x", ABSTFN+"y")
344 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "y"),
345 ABSTFN + "y")
346 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "1"),
347 ABSTFN + "1")
348
349 os.symlink(basename(ABSTFN) + "a/b", ABSTFN+"a")
350 self.assertEqual(realpath(ABSTFN+"a"), ABSTFN+"a/b")
351
352 os.symlink("../" + basename(dirname(ABSTFN)) + "/" +
353 basename(ABSTFN) + "c", ABSTFN+"c")
354 self.assertEqual(realpath(ABSTFN+"c"), ABSTFN+"c")
355
Brian Curtind40e6f72010-07-08 21:39:08 +0000356 # Test using relative path as well.
357 os.chdir(dirname(ABSTFN))
358 self.assertEqual(realpath(basename(ABSTFN)), ABSTFN)
359 finally:
360 os.chdir(old_path)
361 support.unlink(ABSTFN)
362 support.unlink(ABSTFN+"1")
363 support.unlink(ABSTFN+"2")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200364 support.unlink(ABSTFN+"y")
365 support.unlink(ABSTFN+"c")
Ezio Melotti136726c2013-03-01 20:59:17 +0200366 support.unlink(ABSTFN+"a")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200367
368 @unittest.skipUnless(hasattr(os, "symlink"),
369 "Missing symlink implementation")
370 @skip_if_ABSTFN_contains_backslash
371 def test_realpath_repeated_indirect_symlinks(self):
372 # Issue #6975.
373 try:
374 os.mkdir(ABSTFN)
375 os.symlink('../' + basename(ABSTFN), ABSTFN + '/self')
376 os.symlink('self/self/self', ABSTFN + '/link')
377 self.assertEqual(realpath(ABSTFN + '/link'), ABSTFN)
378 finally:
379 support.unlink(ABSTFN + '/self')
380 support.unlink(ABSTFN + '/link')
381 safe_rmdir(ABSTFN)
382
383 @unittest.skipUnless(hasattr(os, "symlink"),
384 "Missing symlink implementation")
385 @skip_if_ABSTFN_contains_backslash
386 def test_realpath_deep_recursion(self):
387 depth = 10
388 old_path = abspath('.')
389 try:
390 os.mkdir(ABSTFN)
391 for i in range(depth):
392 os.symlink('/'.join(['%d' % i] * 10), ABSTFN + '/%d' % (i + 1))
393 os.symlink('.', ABSTFN + '/0')
394 self.assertEqual(realpath(ABSTFN + '/%d' % depth), ABSTFN)
395
396 # Test using relative path as well.
397 os.chdir(ABSTFN)
398 self.assertEqual(realpath('%d' % depth), ABSTFN)
399 finally:
400 os.chdir(old_path)
401 for i in range(depth + 1):
402 support.unlink(ABSTFN + '/%d' % i)
403 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000404
Brian Curtin52173d42010-12-02 18:29:18 +0000405 @unittest.skipUnless(hasattr(os, "symlink"),
406 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000407 @skip_if_ABSTFN_contains_backslash
408 def test_realpath_resolve_parents(self):
409 # We also need to resolve any symlinks in the parents of a relative
410 # path passed to realpath. E.g.: current working directory is
411 # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call
412 # realpath("a"). This should return /usr/share/doc/a/.
413 try:
414 old_path = abspath('.')
415 os.mkdir(ABSTFN)
416 os.mkdir(ABSTFN + "/y")
417 os.symlink(ABSTFN + "/y", ABSTFN + "/k")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000418
Brian Curtind40e6f72010-07-08 21:39:08 +0000419 os.chdir(ABSTFN + "/k")
420 self.assertEqual(realpath("a"), ABSTFN + "/y/a")
421 finally:
422 os.chdir(old_path)
423 support.unlink(ABSTFN + "/k")
424 safe_rmdir(ABSTFN + "/y")
425 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000426
Brian Curtin52173d42010-12-02 18:29:18 +0000427 @unittest.skipUnless(hasattr(os, "symlink"),
428 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000429 @skip_if_ABSTFN_contains_backslash
430 def test_realpath_resolve_before_normalizing(self):
431 # Bug #990669: Symbolic links should be resolved before we
432 # normalize the path. E.g.: if we have directories 'a', 'k' and 'y'
433 # in the following hierarchy:
434 # a/k/y
435 #
436 # and a symbolic link 'link-y' pointing to 'y' in directory 'a',
437 # then realpath("link-y/..") should return 'k', not 'a'.
438 try:
439 old_path = abspath('.')
440 os.mkdir(ABSTFN)
441 os.mkdir(ABSTFN + "/k")
442 os.mkdir(ABSTFN + "/k/y")
443 os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000444
Brian Curtind40e6f72010-07-08 21:39:08 +0000445 # Absolute path.
446 self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k")
447 # Relative path.
448 os.chdir(dirname(ABSTFN))
449 self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."),
450 ABSTFN + "/k")
451 finally:
452 os.chdir(old_path)
453 support.unlink(ABSTFN + "/link-y")
454 safe_rmdir(ABSTFN + "/k/y")
455 safe_rmdir(ABSTFN + "/k")
456 safe_rmdir(ABSTFN)
Tim Peters5d36a552005-06-03 22:40:27 +0000457
Brian Curtin52173d42010-12-02 18:29:18 +0000458 @unittest.skipUnless(hasattr(os, "symlink"),
459 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000460 @skip_if_ABSTFN_contains_backslash
461 def test_realpath_resolve_first(self):
462 # Bug #1213894: The first component of the path, if not absolute,
463 # must be resolved too.
Georg Brandl268e61c2005-06-03 14:28:50 +0000464
Brian Curtind40e6f72010-07-08 21:39:08 +0000465 try:
466 old_path = abspath('.')
467 os.mkdir(ABSTFN)
468 os.mkdir(ABSTFN + "/k")
469 os.symlink(ABSTFN, ABSTFN + "link")
470 os.chdir(dirname(ABSTFN))
Tim Peters5d36a552005-06-03 22:40:27 +0000471
Brian Curtind40e6f72010-07-08 21:39:08 +0000472 base = basename(ABSTFN)
473 self.assertEqual(realpath(base + "link"), ABSTFN)
474 self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k")
475 finally:
476 os.chdir(old_path)
477 support.unlink(ABSTFN + "link")
478 safe_rmdir(ABSTFN + "/k")
479 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000480
Guido van Rossumd8faa362007-04-27 19:54:29 +0000481 def test_relpath(self):
482 (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar")
483 try:
484 curdir = os.path.split(os.getcwd())[-1]
485 self.assertRaises(ValueError, posixpath.relpath, "")
486 self.assertEqual(posixpath.relpath("a"), "a")
487 self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a")
488 self.assertEqual(posixpath.relpath("a/b"), "a/b")
489 self.assertEqual(posixpath.relpath("../a/b"), "../a/b")
490 self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000491 self.assertEqual(posixpath.relpath("a/b", "../c"),
492 "../"+curdir+"/a/b")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000493 self.assertEqual(posixpath.relpath("a", "b/c"), "../../a")
Christian Heimesfaf2f632008-01-06 16:59:19 +0000494 self.assertEqual(posixpath.relpath("a", "a"), ".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000495 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x/y/z"), '../../../foo/bar/bat')
496 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/foo/bar"), 'bat')
497 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/"), 'foo/bar/bat')
498 self.assertEqual(posixpath.relpath("/", "/foo/bar/bat"), '../../..')
499 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x"), '../foo/bar/bat')
500 self.assertEqual(posixpath.relpath("/x", "/foo/bar/bat"), '../../../x')
501 self.assertEqual(posixpath.relpath("/", "/"), '.')
502 self.assertEqual(posixpath.relpath("/a", "/a"), '.')
503 self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000504 finally:
505 os.getcwd = real_getcwd
Brett Cannonb47243a2003-06-16 21:54:50 +0000506
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000507 def test_relpath_bytes(self):
508 (real_getcwdb, os.getcwdb) = (os.getcwdb, lambda: br"/home/user/bar")
509 try:
510 curdir = os.path.split(os.getcwdb())[-1]
511 self.assertRaises(ValueError, posixpath.relpath, b"")
512 self.assertEqual(posixpath.relpath(b"a"), b"a")
513 self.assertEqual(posixpath.relpath(posixpath.abspath(b"a")), b"a")
514 self.assertEqual(posixpath.relpath(b"a/b"), b"a/b")
515 self.assertEqual(posixpath.relpath(b"../a/b"), b"../a/b")
516 self.assertEqual(posixpath.relpath(b"a", b"../b"),
517 b"../"+curdir+b"/a")
518 self.assertEqual(posixpath.relpath(b"a/b", b"../c"),
519 b"../"+curdir+b"/a/b")
520 self.assertEqual(posixpath.relpath(b"a", b"b/c"), b"../../a")
521 self.assertEqual(posixpath.relpath(b"a", b"a"), b".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000522 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x/y/z"), b'../../../foo/bar/bat')
523 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/foo/bar"), b'bat')
524 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/"), b'foo/bar/bat')
525 self.assertEqual(posixpath.relpath(b"/", b"/foo/bar/bat"), b'../../..')
526 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x"), b'../foo/bar/bat')
527 self.assertEqual(posixpath.relpath(b"/x", b"/foo/bar/bat"), b'../../../x')
528 self.assertEqual(posixpath.relpath(b"/", b"/"), b'.')
529 self.assertEqual(posixpath.relpath(b"/a", b"/a"), b'.')
530 self.assertEqual(posixpath.relpath(b"/a/b", b"/a/b"), b'.')
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000531
532 self.assertRaises(TypeError, posixpath.relpath, b"bytes", "str")
533 self.assertRaises(TypeError, posixpath.relpath, "str", b"bytes")
534 finally:
535 os.getcwdb = real_getcwdb
536
Florent Xiclunac9c79782010-03-08 12:24:53 +0000537
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200538class PosixCommonTest(test_genericpath.CommonTest, unittest.TestCase):
Florent Xiclunac9c79782010-03-08 12:24:53 +0000539 pathmodule = posixpath
540 attributes = ['relpath', 'samefile', 'sameopenfile', 'samestat']
541
542
Brett Cannonb47243a2003-06-16 21:54:50 +0000543if __name__=="__main__":
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200544 unittest.main()