blob: 1d4596e7b17499e6826c2dc55c19c2b2eaf25815 [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:
Brian Curtind40e6f72010-07-08 21:39:08 +0000331 os.symlink(ABSTFN, ABSTFN)
332 self.assertEqual(realpath(ABSTFN), ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000333
Brian Curtind40e6f72010-07-08 21:39:08 +0000334 os.symlink(ABSTFN+"1", ABSTFN+"2")
335 os.symlink(ABSTFN+"2", ABSTFN+"1")
336 self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1")
337 self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000338
Serhiy Storchakadf326912013-02-10 12:22:07 +0200339 self.assertEqual(realpath(ABSTFN+"1/x"), ABSTFN+"1/x")
340 self.assertEqual(realpath(ABSTFN+"1/.."), dirname(ABSTFN))
341 self.assertEqual(realpath(ABSTFN+"1/../x"), dirname(ABSTFN) + "/x")
342 os.symlink(ABSTFN+"x", ABSTFN+"y")
343 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "y"),
344 ABSTFN + "y")
345 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "1"),
346 ABSTFN + "1")
347
348 os.symlink(basename(ABSTFN) + "a/b", ABSTFN+"a")
349 self.assertEqual(realpath(ABSTFN+"a"), ABSTFN+"a/b")
350
351 os.symlink("../" + basename(dirname(ABSTFN)) + "/" +
352 basename(ABSTFN) + "c", ABSTFN+"c")
353 self.assertEqual(realpath(ABSTFN+"c"), ABSTFN+"c")
354
Brian Curtind40e6f72010-07-08 21:39:08 +0000355 # Test using relative path as well.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300356 with support.change_cwd(dirname(ABSTFN)):
357 self.assertEqual(realpath(basename(ABSTFN)), ABSTFN)
Brian Curtind40e6f72010-07-08 21:39:08 +0000358 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000359 support.unlink(ABSTFN)
360 support.unlink(ABSTFN+"1")
361 support.unlink(ABSTFN+"2")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200362 support.unlink(ABSTFN+"y")
363 support.unlink(ABSTFN+"c")
Ezio Melotti136726c2013-03-01 20:59:17 +0200364 support.unlink(ABSTFN+"a")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200365
366 @unittest.skipUnless(hasattr(os, "symlink"),
367 "Missing symlink implementation")
368 @skip_if_ABSTFN_contains_backslash
369 def test_realpath_repeated_indirect_symlinks(self):
370 # Issue #6975.
371 try:
372 os.mkdir(ABSTFN)
373 os.symlink('../' + basename(ABSTFN), ABSTFN + '/self')
374 os.symlink('self/self/self', ABSTFN + '/link')
375 self.assertEqual(realpath(ABSTFN + '/link'), ABSTFN)
376 finally:
377 support.unlink(ABSTFN + '/self')
378 support.unlink(ABSTFN + '/link')
379 safe_rmdir(ABSTFN)
380
381 @unittest.skipUnless(hasattr(os, "symlink"),
382 "Missing symlink implementation")
383 @skip_if_ABSTFN_contains_backslash
384 def test_realpath_deep_recursion(self):
385 depth = 10
Serhiy Storchakadf326912013-02-10 12:22:07 +0200386 try:
387 os.mkdir(ABSTFN)
388 for i in range(depth):
389 os.symlink('/'.join(['%d' % i] * 10), ABSTFN + '/%d' % (i + 1))
390 os.symlink('.', ABSTFN + '/0')
391 self.assertEqual(realpath(ABSTFN + '/%d' % depth), ABSTFN)
392
393 # Test using relative path as well.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300394 with support.change_cwd(ABSTFN):
395 self.assertEqual(realpath('%d' % depth), ABSTFN)
Serhiy Storchakadf326912013-02-10 12:22:07 +0200396 finally:
Serhiy Storchakadf326912013-02-10 12:22:07 +0200397 for i in range(depth + 1):
398 support.unlink(ABSTFN + '/%d' % i)
399 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000400
Brian Curtin52173d42010-12-02 18:29:18 +0000401 @unittest.skipUnless(hasattr(os, "symlink"),
402 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000403 @skip_if_ABSTFN_contains_backslash
404 def test_realpath_resolve_parents(self):
405 # We also need to resolve any symlinks in the parents of a relative
406 # path passed to realpath. E.g.: current working directory is
407 # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call
408 # realpath("a"). This should return /usr/share/doc/a/.
409 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000410 os.mkdir(ABSTFN)
411 os.mkdir(ABSTFN + "/y")
412 os.symlink(ABSTFN + "/y", ABSTFN + "/k")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000413
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300414 with support.change_cwd(ABSTFN + "/k"):
415 self.assertEqual(realpath("a"), ABSTFN + "/y/a")
Brian Curtind40e6f72010-07-08 21:39:08 +0000416 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000417 support.unlink(ABSTFN + "/k")
418 safe_rmdir(ABSTFN + "/y")
419 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000420
Brian Curtin52173d42010-12-02 18:29:18 +0000421 @unittest.skipUnless(hasattr(os, "symlink"),
422 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000423 @skip_if_ABSTFN_contains_backslash
424 def test_realpath_resolve_before_normalizing(self):
425 # Bug #990669: Symbolic links should be resolved before we
426 # normalize the path. E.g.: if we have directories 'a', 'k' and 'y'
427 # in the following hierarchy:
428 # a/k/y
429 #
430 # and a symbolic link 'link-y' pointing to 'y' in directory 'a',
431 # then realpath("link-y/..") should return 'k', not 'a'.
432 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000433 os.mkdir(ABSTFN)
434 os.mkdir(ABSTFN + "/k")
435 os.mkdir(ABSTFN + "/k/y")
436 os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000437
Brian Curtind40e6f72010-07-08 21:39:08 +0000438 # Absolute path.
439 self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k")
440 # Relative path.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300441 with support.change_cwd(dirname(ABSTFN)):
442 self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."),
443 ABSTFN + "/k")
Brian Curtind40e6f72010-07-08 21:39:08 +0000444 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000445 support.unlink(ABSTFN + "/link-y")
446 safe_rmdir(ABSTFN + "/k/y")
447 safe_rmdir(ABSTFN + "/k")
448 safe_rmdir(ABSTFN)
Tim Peters5d36a552005-06-03 22:40:27 +0000449
Brian Curtin52173d42010-12-02 18:29:18 +0000450 @unittest.skipUnless(hasattr(os, "symlink"),
451 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000452 @skip_if_ABSTFN_contains_backslash
453 def test_realpath_resolve_first(self):
454 # Bug #1213894: The first component of the path, if not absolute,
455 # must be resolved too.
Georg Brandl268e61c2005-06-03 14:28:50 +0000456
Brian Curtind40e6f72010-07-08 21:39:08 +0000457 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000458 os.mkdir(ABSTFN)
459 os.mkdir(ABSTFN + "/k")
460 os.symlink(ABSTFN, ABSTFN + "link")
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300461 with support.change_cwd(dirname(ABSTFN)):
462 base = basename(ABSTFN)
463 self.assertEqual(realpath(base + "link"), ABSTFN)
464 self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k")
Brian Curtind40e6f72010-07-08 21:39:08 +0000465 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000466 support.unlink(ABSTFN + "link")
467 safe_rmdir(ABSTFN + "/k")
468 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000469
Guido van Rossumd8faa362007-04-27 19:54:29 +0000470 def test_relpath(self):
471 (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar")
472 try:
473 curdir = os.path.split(os.getcwd())[-1]
474 self.assertRaises(ValueError, posixpath.relpath, "")
475 self.assertEqual(posixpath.relpath("a"), "a")
476 self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a")
477 self.assertEqual(posixpath.relpath("a/b"), "a/b")
478 self.assertEqual(posixpath.relpath("../a/b"), "../a/b")
479 self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000480 self.assertEqual(posixpath.relpath("a/b", "../c"),
481 "../"+curdir+"/a/b")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000482 self.assertEqual(posixpath.relpath("a", "b/c"), "../../a")
Christian Heimesfaf2f632008-01-06 16:59:19 +0000483 self.assertEqual(posixpath.relpath("a", "a"), ".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000484 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x/y/z"), '../../../foo/bar/bat')
485 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/foo/bar"), 'bat')
486 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/"), 'foo/bar/bat')
487 self.assertEqual(posixpath.relpath("/", "/foo/bar/bat"), '../../..')
488 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x"), '../foo/bar/bat')
489 self.assertEqual(posixpath.relpath("/x", "/foo/bar/bat"), '../../../x')
490 self.assertEqual(posixpath.relpath("/", "/"), '.')
491 self.assertEqual(posixpath.relpath("/a", "/a"), '.')
492 self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000493 finally:
494 os.getcwd = real_getcwd
Brett Cannonb47243a2003-06-16 21:54:50 +0000495
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000496 def test_relpath_bytes(self):
497 (real_getcwdb, os.getcwdb) = (os.getcwdb, lambda: br"/home/user/bar")
498 try:
499 curdir = os.path.split(os.getcwdb())[-1]
500 self.assertRaises(ValueError, posixpath.relpath, b"")
501 self.assertEqual(posixpath.relpath(b"a"), b"a")
502 self.assertEqual(posixpath.relpath(posixpath.abspath(b"a")), b"a")
503 self.assertEqual(posixpath.relpath(b"a/b"), b"a/b")
504 self.assertEqual(posixpath.relpath(b"../a/b"), b"../a/b")
505 self.assertEqual(posixpath.relpath(b"a", b"../b"),
506 b"../"+curdir+b"/a")
507 self.assertEqual(posixpath.relpath(b"a/b", b"../c"),
508 b"../"+curdir+b"/a/b")
509 self.assertEqual(posixpath.relpath(b"a", b"b/c"), b"../../a")
510 self.assertEqual(posixpath.relpath(b"a", b"a"), b".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000511 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x/y/z"), b'../../../foo/bar/bat')
512 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/foo/bar"), b'bat')
513 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/"), b'foo/bar/bat')
514 self.assertEqual(posixpath.relpath(b"/", b"/foo/bar/bat"), b'../../..')
515 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x"), b'../foo/bar/bat')
516 self.assertEqual(posixpath.relpath(b"/x", b"/foo/bar/bat"), b'../../../x')
517 self.assertEqual(posixpath.relpath(b"/", b"/"), b'.')
518 self.assertEqual(posixpath.relpath(b"/a", b"/a"), b'.')
519 self.assertEqual(posixpath.relpath(b"/a/b", b"/a/b"), b'.')
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000520
521 self.assertRaises(TypeError, posixpath.relpath, b"bytes", "str")
522 self.assertRaises(TypeError, posixpath.relpath, "str", b"bytes")
523 finally:
524 os.getcwdb = real_getcwdb
525
Florent Xiclunac9c79782010-03-08 12:24:53 +0000526
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200527class PosixCommonTest(test_genericpath.CommonTest, unittest.TestCase):
Florent Xiclunac9c79782010-03-08 12:24:53 +0000528 pathmodule = posixpath
529 attributes = ['relpath', 'samefile', 'sameopenfile', 'samestat']
530
531
Brett Cannonb47243a2003-06-16 21:54:50 +0000532if __name__=="__main__":
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200533 unittest.main()