blob: 412849cff3a3a006a7700efbf22589af422f1fa9 [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
Hynek Schlawackc5a45662012-07-17 13:05:43 +020060 def check_error_msg(list_of_args, msg):
61 """Check posixpath.join raises friendly TypeErrors."""
62 for args in (item for perm in list_of_args
63 for item in itertools.permutations(perm)):
Hynek Schlawack7cdc2bd2012-07-17 10:48:19 +020064 with self.assertRaises(TypeError) as cm:
65 posixpath.join(*args)
Hynek Schlawackc5a45662012-07-17 13:05:43 +020066 self.assertEqual(msg, cm.exception.args[0])
Hynek Schlawack7cdc2bd2012-07-17 10:48:19 +020067
Hynek Schlawackc5a45662012-07-17 13:05:43 +020068 check_error_msg([[b'bytes', 'str'], [bytearray(b'bytes'), 'str']],
69 "Can't mix strings and bytes in path components.")
70 # regression, see #15377
71 with self.assertRaises(TypeError) as cm:
Hynek Schlawack0b350c62012-07-17 14:28:44 +020072 posixpath.join(None, 'str')
Hynek Schlawackc5a45662012-07-17 13:05:43 +020073 self.assertNotEqual("Can't mix strings and bytes in path components.",
74 cm.exception.args[0])
Skip Montanaroe809b002000-07-12 00:20:08 +000075
Brett Cannonb47243a2003-06-16 21:54:50 +000076 def test_split(self):
77 self.assertEqual(posixpath.split("/foo/bar"), ("/foo", "bar"))
78 self.assertEqual(posixpath.split("/"), ("/", ""))
79 self.assertEqual(posixpath.split("foo"), ("", "foo"))
80 self.assertEqual(posixpath.split("////foo"), ("////", "foo"))
81 self.assertEqual(posixpath.split("//foo//bar"), ("//foo", "bar"))
82
Guido van Rossumf0af3e32008-10-02 18:55:37 +000083 self.assertEqual(posixpath.split(b"/foo/bar"), (b"/foo", b"bar"))
84 self.assertEqual(posixpath.split(b"/"), (b"/", b""))
85 self.assertEqual(posixpath.split(b"foo"), (b"", b"foo"))
86 self.assertEqual(posixpath.split(b"////foo"), (b"////", b"foo"))
87 self.assertEqual(posixpath.split(b"//foo//bar"), (b"//foo", b"bar"))
88
Guido van Rossumd8faa362007-04-27 19:54:29 +000089 def splitextTest(self, path, filename, ext):
90 self.assertEqual(posixpath.splitext(path), (filename, ext))
91 self.assertEqual(posixpath.splitext("/" + path), ("/" + filename, ext))
Guido van Rossumf0af3e32008-10-02 18:55:37 +000092 self.assertEqual(posixpath.splitext("abc/" + path),
93 ("abc/" + filename, ext))
94 self.assertEqual(posixpath.splitext("abc.def/" + path),
95 ("abc.def/" + filename, ext))
96 self.assertEqual(posixpath.splitext("/abc.def/" + path),
97 ("/abc.def/" + filename, ext))
98 self.assertEqual(posixpath.splitext(path + "/"),
99 (filename + ext + "/", ""))
100
101 path = bytes(path, "ASCII")
102 filename = bytes(filename, "ASCII")
103 ext = bytes(ext, "ASCII")
104
105 self.assertEqual(posixpath.splitext(path), (filename, ext))
106 self.assertEqual(posixpath.splitext(b"/" + path),
107 (b"/" + filename, ext))
108 self.assertEqual(posixpath.splitext(b"abc/" + path),
109 (b"abc/" + filename, ext))
110 self.assertEqual(posixpath.splitext(b"abc.def/" + path),
111 (b"abc.def/" + filename, ext))
112 self.assertEqual(posixpath.splitext(b"/abc.def/" + path),
113 (b"/abc.def/" + filename, ext))
114 self.assertEqual(posixpath.splitext(path + b"/"),
115 (filename + ext + b"/", b""))
Brett Cannonb47243a2003-06-16 21:54:50 +0000116
Guido van Rossumd8faa362007-04-27 19:54:29 +0000117 def test_splitext(self):
118 self.splitextTest("foo.bar", "foo", ".bar")
119 self.splitextTest("foo.boo.bar", "foo.boo", ".bar")
120 self.splitextTest("foo.boo.biff.bar", "foo.boo.biff", ".bar")
121 self.splitextTest(".csh.rc", ".csh", ".rc")
122 self.splitextTest("nodots", "nodots", "")
123 self.splitextTest(".cshrc", ".cshrc", "")
124 self.splitextTest("...manydots", "...manydots", "")
125 self.splitextTest("...manydots.ext", "...manydots", ".ext")
126 self.splitextTest(".", ".", "")
127 self.splitextTest("..", "..", "")
128 self.splitextTest("........", "........", "")
129 self.splitextTest("", "", "")
Brett Cannonb47243a2003-06-16 21:54:50 +0000130
131 def test_isabs(self):
132 self.assertIs(posixpath.isabs(""), False)
133 self.assertIs(posixpath.isabs("/"), True)
134 self.assertIs(posixpath.isabs("/foo"), True)
135 self.assertIs(posixpath.isabs("/foo/bar"), True)
136 self.assertIs(posixpath.isabs("foo/bar"), False)
137
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000138 self.assertIs(posixpath.isabs(b""), False)
139 self.assertIs(posixpath.isabs(b"/"), True)
140 self.assertIs(posixpath.isabs(b"/foo"), True)
141 self.assertIs(posixpath.isabs(b"/foo/bar"), True)
142 self.assertIs(posixpath.isabs(b"foo/bar"), False)
143
Brett Cannonb47243a2003-06-16 21:54:50 +0000144 def test_basename(self):
145 self.assertEqual(posixpath.basename("/foo/bar"), "bar")
146 self.assertEqual(posixpath.basename("/"), "")
147 self.assertEqual(posixpath.basename("foo"), "foo")
148 self.assertEqual(posixpath.basename("////foo"), "foo")
149 self.assertEqual(posixpath.basename("//foo//bar"), "bar")
150
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000151 self.assertEqual(posixpath.basename(b"/foo/bar"), b"bar")
152 self.assertEqual(posixpath.basename(b"/"), b"")
153 self.assertEqual(posixpath.basename(b"foo"), b"foo")
154 self.assertEqual(posixpath.basename(b"////foo"), b"foo")
155 self.assertEqual(posixpath.basename(b"//foo//bar"), b"bar")
156
Brett Cannonb47243a2003-06-16 21:54:50 +0000157 def test_dirname(self):
158 self.assertEqual(posixpath.dirname("/foo/bar"), "/foo")
159 self.assertEqual(posixpath.dirname("/"), "/")
160 self.assertEqual(posixpath.dirname("foo"), "")
161 self.assertEqual(posixpath.dirname("////foo"), "////")
162 self.assertEqual(posixpath.dirname("//foo//bar"), "//foo")
163
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000164 self.assertEqual(posixpath.dirname(b"/foo/bar"), b"/foo")
165 self.assertEqual(posixpath.dirname(b"/"), b"/")
166 self.assertEqual(posixpath.dirname(b"foo"), b"")
167 self.assertEqual(posixpath.dirname(b"////foo"), b"////")
168 self.assertEqual(posixpath.dirname(b"//foo//bar"), b"//foo")
169
Brett Cannonb47243a2003-06-16 21:54:50 +0000170 def test_islink(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000171 self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
Michael Foord07926f02011-03-16 17:19:16 -0400172 self.assertIs(posixpath.lexists(support.TESTFN + "2"), False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000173 f = open(support.TESTFN + "1", "wb")
Brett Cannonb47243a2003-06-16 21:54:50 +0000174 try:
Guido van Rossum7dcb8442007-08-27 23:26:56 +0000175 f.write(b"foo")
Brett Cannonb47243a2003-06-16 21:54:50 +0000176 f.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000177 self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
Brian Curtin3b4499c2010-12-28 14:31:47 +0000178 if support.can_symlink():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000179 os.symlink(support.TESTFN + "1", support.TESTFN + "2")
180 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
181 os.remove(support.TESTFN + "1")
182 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
183 self.assertIs(posixpath.exists(support.TESTFN + "2"), False)
184 self.assertIs(posixpath.lexists(support.TESTFN + "2"), True)
Brett Cannonb47243a2003-06-16 21:54:50 +0000185 finally:
186 if not f.close():
187 f.close()
Brett Cannonb47243a2003-06-16 21:54:50 +0000188
Brett Cannonb47243a2003-06-16 21:54:50 +0000189 def test_ismount(self):
190 self.assertIs(posixpath.ismount("/"), True)
Victor Stinner1ab6c2d2011-11-15 22:27:41 +0100191 with warnings.catch_warnings():
192 warnings.simplefilter("ignore", DeprecationWarning)
193 self.assertIs(posixpath.ismount(b"/"), True)
Michael Foord07926f02011-03-16 17:19:16 -0400194
195 def test_ismount_non_existent(self):
196 # Non-existent mountpoint.
197 self.assertIs(posixpath.ismount(ABSTFN), False)
198 try:
199 os.mkdir(ABSTFN)
200 self.assertIs(posixpath.ismount(ABSTFN), False)
201 finally:
202 safe_rmdir(ABSTFN)
203
204 @unittest.skipUnless(support.can_symlink(),
205 "Test requires symlink support")
206 def test_ismount_symlinks(self):
207 # Symlinks are never mountpoints.
208 try:
209 os.symlink("/", ABSTFN)
210 self.assertIs(posixpath.ismount(ABSTFN), False)
211 finally:
212 os.unlink(ABSTFN)
213
214 @unittest.skipIf(posix is None, "Test requires posix module")
215 def test_ismount_different_device(self):
216 # Simulate the path being on a different device from its parent by
217 # mocking out st_dev.
218 save_lstat = os.lstat
219 def fake_lstat(path):
220 st_ino = 0
221 st_dev = 0
222 if path == ABSTFN:
223 st_dev = 1
224 st_ino = 1
225 return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
226 try:
227 os.lstat = fake_lstat
228 self.assertIs(posixpath.ismount(ABSTFN), True)
229 finally:
230 os.lstat = save_lstat
Brett Cannonb47243a2003-06-16 21:54:50 +0000231
Brett Cannonb47243a2003-06-16 21:54:50 +0000232 def test_expanduser(self):
233 self.assertEqual(posixpath.expanduser("foo"), "foo")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000234 self.assertEqual(posixpath.expanduser(b"foo"), b"foo")
Brett Cannonb47243a2003-06-16 21:54:50 +0000235 try:
236 import pwd
237 except ImportError:
238 pass
239 else:
Ezio Melottie9615932010-01-24 19:26:24 +0000240 self.assertIsInstance(posixpath.expanduser("~/"), str)
241 self.assertIsInstance(posixpath.expanduser(b"~/"), bytes)
Neal Norwitz168e73d2003-07-01 03:33:31 +0000242 # if home directory == root directory, this test makes no sense
243 if posixpath.expanduser("~") != '/':
244 self.assertEqual(
245 posixpath.expanduser("~") + "/",
246 posixpath.expanduser("~/")
247 )
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000248 self.assertEqual(
249 posixpath.expanduser(b"~") + b"/",
250 posixpath.expanduser(b"~/")
251 )
Ezio Melottie9615932010-01-24 19:26:24 +0000252 self.assertIsInstance(posixpath.expanduser("~root/"), str)
253 self.assertIsInstance(posixpath.expanduser("~foo/"), str)
254 self.assertIsInstance(posixpath.expanduser(b"~root/"), bytes)
255 self.assertIsInstance(posixpath.expanduser(b"~foo/"), bytes)
Brett Cannonb47243a2003-06-16 21:54:50 +0000256
Hirokazu Yamamoto71959632009-04-27 01:44:28 +0000257 with support.EnvironmentVarGuard() as env:
Walter Dörwald155374d2009-05-01 19:58:58 +0000258 env['HOME'] = '/'
Walter Dörwaldb525e182009-04-26 21:39:21 +0000259 self.assertEqual(posixpath.expanduser("~"), "/")
Jesus Cea7f0d8882012-05-10 05:10:50 +0200260 self.assertEqual(posixpath.expanduser("~/foo"), "/foo")
Michael Foord07926f02011-03-16 17:19:16 -0400261 # expanduser should fall back to using the password database
262 del env['HOME']
263 home = pwd.getpwuid(os.getuid()).pw_dir
Ezio Melottice82d572013-05-09 15:19:45 +0300264 # $HOME can end with a trailing /, so strip it (see #17809)
265 self.assertEqual(posixpath.expanduser("~"), home.rstrip("/"))
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000266
Brett Cannonb47243a2003-06-16 21:54:50 +0000267 def test_normpath(self):
268 self.assertEqual(posixpath.normpath(""), ".")
269 self.assertEqual(posixpath.normpath("/"), "/")
270 self.assertEqual(posixpath.normpath("//"), "//")
271 self.assertEqual(posixpath.normpath("///"), "/")
272 self.assertEqual(posixpath.normpath("///foo/.//bar//"), "/foo/bar")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000273 self.assertEqual(posixpath.normpath("///foo/.//bar//.//..//.//baz"),
274 "/foo/baz")
Brett Cannonb47243a2003-06-16 21:54:50 +0000275 self.assertEqual(posixpath.normpath("///..//./foo/.//bar"), "/foo/bar")
276
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000277 self.assertEqual(posixpath.normpath(b""), b".")
278 self.assertEqual(posixpath.normpath(b"/"), b"/")
279 self.assertEqual(posixpath.normpath(b"//"), b"//")
280 self.assertEqual(posixpath.normpath(b"///"), b"/")
281 self.assertEqual(posixpath.normpath(b"///foo/.//bar//"), b"/foo/bar")
282 self.assertEqual(posixpath.normpath(b"///foo/.//bar//.//..//.//baz"),
283 b"/foo/baz")
284 self.assertEqual(posixpath.normpath(b"///..//./foo/.//bar"),
285 b"/foo/bar")
286
Serhiy Storchaka1548ed62013-02-18 13:32:30 +0200287 @skip_if_ABSTFN_contains_backslash
Serhiy Storchaka467393d2013-02-18 12:21:04 +0200288 def test_realpath_curdir(self):
289 self.assertEqual(realpath('.'), os.getcwd())
290 self.assertEqual(realpath('./.'), os.getcwd())
291 self.assertEqual(realpath('/'.join(['.'] * 100)), os.getcwd())
292
293 self.assertEqual(realpath(b'.'), os.getcwdb())
294 self.assertEqual(realpath(b'./.'), os.getcwdb())
295 self.assertEqual(realpath(b'/'.join([b'.'] * 100)), os.getcwdb())
296
Serhiy Storchaka1548ed62013-02-18 13:32:30 +0200297 @skip_if_ABSTFN_contains_backslash
Serhiy Storchaka467393d2013-02-18 12:21:04 +0200298 def test_realpath_pardir(self):
299 self.assertEqual(realpath('..'), dirname(os.getcwd()))
300 self.assertEqual(realpath('../..'), dirname(dirname(os.getcwd())))
301 self.assertEqual(realpath('/'.join(['..'] * 100)), '/')
302
303 self.assertEqual(realpath(b'..'), dirname(os.getcwdb()))
304 self.assertEqual(realpath(b'../..'), dirname(dirname(os.getcwdb())))
305 self.assertEqual(realpath(b'/'.join([b'..'] * 100)), b'/')
306
Brian Curtin52173d42010-12-02 18:29:18 +0000307 @unittest.skipUnless(hasattr(os, "symlink"),
308 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000309 @skip_if_ABSTFN_contains_backslash
310 def test_realpath_basic(self):
311 # Basic operation.
312 try:
313 os.symlink(ABSTFN+"1", ABSTFN)
314 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
315 finally:
316 support.unlink(ABSTFN)
Tim Petersa45cacf2004-08-20 03:47:14 +0000317
Brian Curtin52173d42010-12-02 18:29:18 +0000318 @unittest.skipUnless(hasattr(os, "symlink"),
319 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000320 @skip_if_ABSTFN_contains_backslash
Michael Foord07926f02011-03-16 17:19:16 -0400321 def test_realpath_relative(self):
322 try:
323 os.symlink(posixpath.relpath(ABSTFN+"1"), ABSTFN)
324 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
325 finally:
326 support.unlink(ABSTFN)
327
328 @unittest.skipUnless(hasattr(os, "symlink"),
329 "Missing symlink implementation")
330 @skip_if_ABSTFN_contains_backslash
Brian Curtind40e6f72010-07-08 21:39:08 +0000331 def test_realpath_symlink_loops(self):
332 # Bug #930024, return the path unchanged if we get into an infinite
333 # symlink loop.
334 try:
335 old_path = abspath('.')
336 os.symlink(ABSTFN, ABSTFN)
337 self.assertEqual(realpath(ABSTFN), ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000338
Brian Curtind40e6f72010-07-08 21:39:08 +0000339 os.symlink(ABSTFN+"1", ABSTFN+"2")
340 os.symlink(ABSTFN+"2", ABSTFN+"1")
341 self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1")
342 self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000343
Serhiy Storchakadf326912013-02-10 12:22:07 +0200344 self.assertEqual(realpath(ABSTFN+"1/x"), ABSTFN+"1/x")
345 self.assertEqual(realpath(ABSTFN+"1/.."), dirname(ABSTFN))
346 self.assertEqual(realpath(ABSTFN+"1/../x"), dirname(ABSTFN) + "/x")
347 os.symlink(ABSTFN+"x", ABSTFN+"y")
348 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "y"),
349 ABSTFN + "y")
350 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "1"),
351 ABSTFN + "1")
352
353 os.symlink(basename(ABSTFN) + "a/b", ABSTFN+"a")
354 self.assertEqual(realpath(ABSTFN+"a"), ABSTFN+"a/b")
355
356 os.symlink("../" + basename(dirname(ABSTFN)) + "/" +
357 basename(ABSTFN) + "c", ABSTFN+"c")
358 self.assertEqual(realpath(ABSTFN+"c"), ABSTFN+"c")
359
Brian Curtind40e6f72010-07-08 21:39:08 +0000360 # Test using relative path as well.
361 os.chdir(dirname(ABSTFN))
362 self.assertEqual(realpath(basename(ABSTFN)), ABSTFN)
363 finally:
364 os.chdir(old_path)
365 support.unlink(ABSTFN)
366 support.unlink(ABSTFN+"1")
367 support.unlink(ABSTFN+"2")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200368 support.unlink(ABSTFN+"y")
369 support.unlink(ABSTFN+"c")
Ezio Melotti136726c2013-03-01 20:59:17 +0200370 support.unlink(ABSTFN+"a")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200371
372 @unittest.skipUnless(hasattr(os, "symlink"),
373 "Missing symlink implementation")
374 @skip_if_ABSTFN_contains_backslash
375 def test_realpath_repeated_indirect_symlinks(self):
376 # Issue #6975.
377 try:
378 os.mkdir(ABSTFN)
379 os.symlink('../' + basename(ABSTFN), ABSTFN + '/self')
380 os.symlink('self/self/self', ABSTFN + '/link')
381 self.assertEqual(realpath(ABSTFN + '/link'), ABSTFN)
382 finally:
383 support.unlink(ABSTFN + '/self')
384 support.unlink(ABSTFN + '/link')
385 safe_rmdir(ABSTFN)
386
387 @unittest.skipUnless(hasattr(os, "symlink"),
388 "Missing symlink implementation")
389 @skip_if_ABSTFN_contains_backslash
390 def test_realpath_deep_recursion(self):
391 depth = 10
392 old_path = abspath('.')
393 try:
394 os.mkdir(ABSTFN)
395 for i in range(depth):
396 os.symlink('/'.join(['%d' % i] * 10), ABSTFN + '/%d' % (i + 1))
397 os.symlink('.', ABSTFN + '/0')
398 self.assertEqual(realpath(ABSTFN + '/%d' % depth), ABSTFN)
399
400 # Test using relative path as well.
401 os.chdir(ABSTFN)
402 self.assertEqual(realpath('%d' % depth), ABSTFN)
403 finally:
404 os.chdir(old_path)
405 for i in range(depth + 1):
406 support.unlink(ABSTFN + '/%d' % i)
407 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000408
Brian Curtin52173d42010-12-02 18:29:18 +0000409 @unittest.skipUnless(hasattr(os, "symlink"),
410 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000411 @skip_if_ABSTFN_contains_backslash
412 def test_realpath_resolve_parents(self):
413 # We also need to resolve any symlinks in the parents of a relative
414 # path passed to realpath. E.g.: current working directory is
415 # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call
416 # realpath("a"). This should return /usr/share/doc/a/.
417 try:
418 old_path = abspath('.')
419 os.mkdir(ABSTFN)
420 os.mkdir(ABSTFN + "/y")
421 os.symlink(ABSTFN + "/y", ABSTFN + "/k")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000422
Brian Curtind40e6f72010-07-08 21:39:08 +0000423 os.chdir(ABSTFN + "/k")
424 self.assertEqual(realpath("a"), ABSTFN + "/y/a")
425 finally:
426 os.chdir(old_path)
427 support.unlink(ABSTFN + "/k")
428 safe_rmdir(ABSTFN + "/y")
429 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000430
Brian Curtin52173d42010-12-02 18:29:18 +0000431 @unittest.skipUnless(hasattr(os, "symlink"),
432 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000433 @skip_if_ABSTFN_contains_backslash
434 def test_realpath_resolve_before_normalizing(self):
435 # Bug #990669: Symbolic links should be resolved before we
436 # normalize the path. E.g.: if we have directories 'a', 'k' and 'y'
437 # in the following hierarchy:
438 # a/k/y
439 #
440 # and a symbolic link 'link-y' pointing to 'y' in directory 'a',
441 # then realpath("link-y/..") should return 'k', not 'a'.
442 try:
443 old_path = abspath('.')
444 os.mkdir(ABSTFN)
445 os.mkdir(ABSTFN + "/k")
446 os.mkdir(ABSTFN + "/k/y")
447 os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000448
Brian Curtind40e6f72010-07-08 21:39:08 +0000449 # Absolute path.
450 self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k")
451 # Relative path.
452 os.chdir(dirname(ABSTFN))
453 self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."),
454 ABSTFN + "/k")
455 finally:
456 os.chdir(old_path)
457 support.unlink(ABSTFN + "/link-y")
458 safe_rmdir(ABSTFN + "/k/y")
459 safe_rmdir(ABSTFN + "/k")
460 safe_rmdir(ABSTFN)
Tim Peters5d36a552005-06-03 22:40:27 +0000461
Brian Curtin52173d42010-12-02 18:29:18 +0000462 @unittest.skipUnless(hasattr(os, "symlink"),
463 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000464 @skip_if_ABSTFN_contains_backslash
465 def test_realpath_resolve_first(self):
466 # Bug #1213894: The first component of the path, if not absolute,
467 # must be resolved too.
Georg Brandl268e61c2005-06-03 14:28:50 +0000468
Brian Curtind40e6f72010-07-08 21:39:08 +0000469 try:
470 old_path = abspath('.')
471 os.mkdir(ABSTFN)
472 os.mkdir(ABSTFN + "/k")
473 os.symlink(ABSTFN, ABSTFN + "link")
474 os.chdir(dirname(ABSTFN))
Tim Peters5d36a552005-06-03 22:40:27 +0000475
Brian Curtind40e6f72010-07-08 21:39:08 +0000476 base = basename(ABSTFN)
477 self.assertEqual(realpath(base + "link"), ABSTFN)
478 self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k")
479 finally:
480 os.chdir(old_path)
481 support.unlink(ABSTFN + "link")
482 safe_rmdir(ABSTFN + "/k")
483 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000484
Guido van Rossumd8faa362007-04-27 19:54:29 +0000485 def test_relpath(self):
486 (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar")
487 try:
488 curdir = os.path.split(os.getcwd())[-1]
489 self.assertRaises(ValueError, posixpath.relpath, "")
490 self.assertEqual(posixpath.relpath("a"), "a")
491 self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a")
492 self.assertEqual(posixpath.relpath("a/b"), "a/b")
493 self.assertEqual(posixpath.relpath("../a/b"), "../a/b")
494 self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000495 self.assertEqual(posixpath.relpath("a/b", "../c"),
496 "../"+curdir+"/a/b")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000497 self.assertEqual(posixpath.relpath("a", "b/c"), "../../a")
Christian Heimesfaf2f632008-01-06 16:59:19 +0000498 self.assertEqual(posixpath.relpath("a", "a"), ".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000499 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x/y/z"), '../../../foo/bar/bat')
500 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/foo/bar"), 'bat')
501 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/"), 'foo/bar/bat')
502 self.assertEqual(posixpath.relpath("/", "/foo/bar/bat"), '../../..')
503 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x"), '../foo/bar/bat')
504 self.assertEqual(posixpath.relpath("/x", "/foo/bar/bat"), '../../../x')
505 self.assertEqual(posixpath.relpath("/", "/"), '.')
506 self.assertEqual(posixpath.relpath("/a", "/a"), '.')
507 self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000508 finally:
509 os.getcwd = real_getcwd
Brett Cannonb47243a2003-06-16 21:54:50 +0000510
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000511 def test_relpath_bytes(self):
512 (real_getcwdb, os.getcwdb) = (os.getcwdb, lambda: br"/home/user/bar")
513 try:
514 curdir = os.path.split(os.getcwdb())[-1]
515 self.assertRaises(ValueError, posixpath.relpath, b"")
516 self.assertEqual(posixpath.relpath(b"a"), b"a")
517 self.assertEqual(posixpath.relpath(posixpath.abspath(b"a")), b"a")
518 self.assertEqual(posixpath.relpath(b"a/b"), b"a/b")
519 self.assertEqual(posixpath.relpath(b"../a/b"), b"../a/b")
520 self.assertEqual(posixpath.relpath(b"a", b"../b"),
521 b"../"+curdir+b"/a")
522 self.assertEqual(posixpath.relpath(b"a/b", b"../c"),
523 b"../"+curdir+b"/a/b")
524 self.assertEqual(posixpath.relpath(b"a", b"b/c"), b"../../a")
525 self.assertEqual(posixpath.relpath(b"a", b"a"), b".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000526 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x/y/z"), b'../../../foo/bar/bat')
527 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/foo/bar"), b'bat')
528 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/"), b'foo/bar/bat')
529 self.assertEqual(posixpath.relpath(b"/", b"/foo/bar/bat"), b'../../..')
530 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x"), b'../foo/bar/bat')
531 self.assertEqual(posixpath.relpath(b"/x", b"/foo/bar/bat"), b'../../../x')
532 self.assertEqual(posixpath.relpath(b"/", b"/"), b'.')
533 self.assertEqual(posixpath.relpath(b"/a", b"/a"), b'.')
534 self.assertEqual(posixpath.relpath(b"/a/b", b"/a/b"), b'.')
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000535
536 self.assertRaises(TypeError, posixpath.relpath, b"bytes", "str")
537 self.assertRaises(TypeError, posixpath.relpath, "str", b"bytes")
538 finally:
539 os.getcwdb = real_getcwdb
540
Florent Xiclunac9c79782010-03-08 12:24:53 +0000541
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200542class PosixCommonTest(test_genericpath.CommonTest, unittest.TestCase):
Florent Xiclunac9c79782010-03-08 12:24:53 +0000543 pathmodule = posixpath
544 attributes = ['relpath', 'samefile', 'sameopenfile', 'samestat']
545
546
Brett Cannonb47243a2003-06-16 21:54:50 +0000547if __name__=="__main__":
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200548 unittest.main()