blob: acf110204cf547867a354ad4e6213032dfb22fe8 [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
Brett Cannonb47243a2003-06-16 21:54:50 +000060 def test_split(self):
61 self.assertEqual(posixpath.split("/foo/bar"), ("/foo", "bar"))
62 self.assertEqual(posixpath.split("/"), ("/", ""))
63 self.assertEqual(posixpath.split("foo"), ("", "foo"))
64 self.assertEqual(posixpath.split("////foo"), ("////", "foo"))
65 self.assertEqual(posixpath.split("//foo//bar"), ("//foo", "bar"))
66
Guido van Rossumf0af3e32008-10-02 18:55:37 +000067 self.assertEqual(posixpath.split(b"/foo/bar"), (b"/foo", b"bar"))
68 self.assertEqual(posixpath.split(b"/"), (b"/", b""))
69 self.assertEqual(posixpath.split(b"foo"), (b"", b"foo"))
70 self.assertEqual(posixpath.split(b"////foo"), (b"////", b"foo"))
71 self.assertEqual(posixpath.split(b"//foo//bar"), (b"//foo", b"bar"))
72
Guido van Rossumd8faa362007-04-27 19:54:29 +000073 def splitextTest(self, path, filename, ext):
74 self.assertEqual(posixpath.splitext(path), (filename, ext))
75 self.assertEqual(posixpath.splitext("/" + path), ("/" + filename, ext))
Guido van Rossumf0af3e32008-10-02 18:55:37 +000076 self.assertEqual(posixpath.splitext("abc/" + path),
77 ("abc/" + filename, ext))
78 self.assertEqual(posixpath.splitext("abc.def/" + path),
79 ("abc.def/" + filename, ext))
80 self.assertEqual(posixpath.splitext("/abc.def/" + path),
81 ("/abc.def/" + filename, ext))
82 self.assertEqual(posixpath.splitext(path + "/"),
83 (filename + ext + "/", ""))
84
85 path = bytes(path, "ASCII")
86 filename = bytes(filename, "ASCII")
87 ext = bytes(ext, "ASCII")
88
89 self.assertEqual(posixpath.splitext(path), (filename, ext))
90 self.assertEqual(posixpath.splitext(b"/" + path),
91 (b"/" + filename, ext))
92 self.assertEqual(posixpath.splitext(b"abc/" + path),
93 (b"abc/" + filename, ext))
94 self.assertEqual(posixpath.splitext(b"abc.def/" + path),
95 (b"abc.def/" + filename, ext))
96 self.assertEqual(posixpath.splitext(b"/abc.def/" + path),
97 (b"/abc.def/" + filename, ext))
98 self.assertEqual(posixpath.splitext(path + b"/"),
99 (filename + ext + b"/", b""))
Brett Cannonb47243a2003-06-16 21:54:50 +0000100
Guido van Rossumd8faa362007-04-27 19:54:29 +0000101 def test_splitext(self):
102 self.splitextTest("foo.bar", "foo", ".bar")
103 self.splitextTest("foo.boo.bar", "foo.boo", ".bar")
104 self.splitextTest("foo.boo.biff.bar", "foo.boo.biff", ".bar")
105 self.splitextTest(".csh.rc", ".csh", ".rc")
106 self.splitextTest("nodots", "nodots", "")
107 self.splitextTest(".cshrc", ".cshrc", "")
108 self.splitextTest("...manydots", "...manydots", "")
109 self.splitextTest("...manydots.ext", "...manydots", ".ext")
110 self.splitextTest(".", ".", "")
111 self.splitextTest("..", "..", "")
112 self.splitextTest("........", "........", "")
113 self.splitextTest("", "", "")
Brett Cannonb47243a2003-06-16 21:54:50 +0000114
115 def test_isabs(self):
116 self.assertIs(posixpath.isabs(""), False)
117 self.assertIs(posixpath.isabs("/"), True)
118 self.assertIs(posixpath.isabs("/foo"), True)
119 self.assertIs(posixpath.isabs("/foo/bar"), True)
120 self.assertIs(posixpath.isabs("foo/bar"), False)
121
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000122 self.assertIs(posixpath.isabs(b""), False)
123 self.assertIs(posixpath.isabs(b"/"), True)
124 self.assertIs(posixpath.isabs(b"/foo"), True)
125 self.assertIs(posixpath.isabs(b"/foo/bar"), True)
126 self.assertIs(posixpath.isabs(b"foo/bar"), False)
127
Brett Cannonb47243a2003-06-16 21:54:50 +0000128 def test_basename(self):
129 self.assertEqual(posixpath.basename("/foo/bar"), "bar")
130 self.assertEqual(posixpath.basename("/"), "")
131 self.assertEqual(posixpath.basename("foo"), "foo")
132 self.assertEqual(posixpath.basename("////foo"), "foo")
133 self.assertEqual(posixpath.basename("//foo//bar"), "bar")
134
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000135 self.assertEqual(posixpath.basename(b"/foo/bar"), b"bar")
136 self.assertEqual(posixpath.basename(b"/"), b"")
137 self.assertEqual(posixpath.basename(b"foo"), b"foo")
138 self.assertEqual(posixpath.basename(b"////foo"), b"foo")
139 self.assertEqual(posixpath.basename(b"//foo//bar"), b"bar")
140
Brett Cannonb47243a2003-06-16 21:54:50 +0000141 def test_dirname(self):
142 self.assertEqual(posixpath.dirname("/foo/bar"), "/foo")
143 self.assertEqual(posixpath.dirname("/"), "/")
144 self.assertEqual(posixpath.dirname("foo"), "")
145 self.assertEqual(posixpath.dirname("////foo"), "////")
146 self.assertEqual(posixpath.dirname("//foo//bar"), "//foo")
147
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000148 self.assertEqual(posixpath.dirname(b"/foo/bar"), b"/foo")
149 self.assertEqual(posixpath.dirname(b"/"), b"/")
150 self.assertEqual(posixpath.dirname(b"foo"), b"")
151 self.assertEqual(posixpath.dirname(b"////foo"), b"////")
152 self.assertEqual(posixpath.dirname(b"//foo//bar"), b"//foo")
153
Brett Cannonb47243a2003-06-16 21:54:50 +0000154 def test_islink(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000155 self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
Michael Foord07926f02011-03-16 17:19:16 -0400156 self.assertIs(posixpath.lexists(support.TESTFN + "2"), False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000157 f = open(support.TESTFN + "1", "wb")
Brett Cannonb47243a2003-06-16 21:54:50 +0000158 try:
Guido van Rossum7dcb8442007-08-27 23:26:56 +0000159 f.write(b"foo")
Brett Cannonb47243a2003-06-16 21:54:50 +0000160 f.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000161 self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
Brian Curtin3b4499c2010-12-28 14:31:47 +0000162 if support.can_symlink():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000163 os.symlink(support.TESTFN + "1", support.TESTFN + "2")
164 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
165 os.remove(support.TESTFN + "1")
166 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
167 self.assertIs(posixpath.exists(support.TESTFN + "2"), False)
168 self.assertIs(posixpath.lexists(support.TESTFN + "2"), True)
Brett Cannonb47243a2003-06-16 21:54:50 +0000169 finally:
170 if not f.close():
171 f.close()
Brett Cannonb47243a2003-06-16 21:54:50 +0000172
Brett Cannonb47243a2003-06-16 21:54:50 +0000173 def test_ismount(self):
174 self.assertIs(posixpath.ismount("/"), True)
Victor Stinner1ab6c2d2011-11-15 22:27:41 +0100175 with warnings.catch_warnings():
176 warnings.simplefilter("ignore", DeprecationWarning)
177 self.assertIs(posixpath.ismount(b"/"), True)
Michael Foord07926f02011-03-16 17:19:16 -0400178
179 def test_ismount_non_existent(self):
180 # Non-existent mountpoint.
181 self.assertIs(posixpath.ismount(ABSTFN), False)
182 try:
183 os.mkdir(ABSTFN)
184 self.assertIs(posixpath.ismount(ABSTFN), False)
185 finally:
186 safe_rmdir(ABSTFN)
187
188 @unittest.skipUnless(support.can_symlink(),
189 "Test requires symlink support")
190 def test_ismount_symlinks(self):
191 # Symlinks are never mountpoints.
192 try:
193 os.symlink("/", ABSTFN)
194 self.assertIs(posixpath.ismount(ABSTFN), False)
195 finally:
196 os.unlink(ABSTFN)
197
198 @unittest.skipIf(posix is None, "Test requires posix module")
199 def test_ismount_different_device(self):
200 # Simulate the path being on a different device from its parent by
201 # mocking out st_dev.
202 save_lstat = os.lstat
203 def fake_lstat(path):
204 st_ino = 0
205 st_dev = 0
206 if path == ABSTFN:
207 st_dev = 1
208 st_ino = 1
209 return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
210 try:
211 os.lstat = fake_lstat
212 self.assertIs(posixpath.ismount(ABSTFN), True)
213 finally:
214 os.lstat = save_lstat
Brett Cannonb47243a2003-06-16 21:54:50 +0000215
Brett Cannonb47243a2003-06-16 21:54:50 +0000216 def test_expanduser(self):
217 self.assertEqual(posixpath.expanduser("foo"), "foo")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000218 self.assertEqual(posixpath.expanduser(b"foo"), b"foo")
Serhiy Storchakaa3fd0b22016-05-03 21:17:03 +0300219 with support.EnvironmentVarGuard() as env:
220 for home in '/', '', '//', '///':
221 with self.subTest(home=home):
222 env['HOME'] = home
223 self.assertEqual(posixpath.expanduser("~"), "/")
224 self.assertEqual(posixpath.expanduser("~/"), "/")
225 self.assertEqual(posixpath.expanduser("~/foo"), "/foo")
Brett Cannonb47243a2003-06-16 21:54:50 +0000226 try:
227 import pwd
228 except ImportError:
229 pass
230 else:
Ezio Melottie9615932010-01-24 19:26:24 +0000231 self.assertIsInstance(posixpath.expanduser("~/"), str)
232 self.assertIsInstance(posixpath.expanduser(b"~/"), bytes)
Neal Norwitz168e73d2003-07-01 03:33:31 +0000233 # if home directory == root directory, this test makes no sense
234 if posixpath.expanduser("~") != '/':
235 self.assertEqual(
236 posixpath.expanduser("~") + "/",
237 posixpath.expanduser("~/")
238 )
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000239 self.assertEqual(
240 posixpath.expanduser(b"~") + b"/",
241 posixpath.expanduser(b"~/")
242 )
Ezio Melottie9615932010-01-24 19:26:24 +0000243 self.assertIsInstance(posixpath.expanduser("~root/"), str)
244 self.assertIsInstance(posixpath.expanduser("~foo/"), str)
245 self.assertIsInstance(posixpath.expanduser(b"~root/"), bytes)
246 self.assertIsInstance(posixpath.expanduser(b"~foo/"), bytes)
Brett Cannonb47243a2003-06-16 21:54:50 +0000247
Hirokazu Yamamoto71959632009-04-27 01:44:28 +0000248 with support.EnvironmentVarGuard() as env:
Michael Foord07926f02011-03-16 17:19:16 -0400249 # expanduser should fall back to using the password database
250 del env['HOME']
251 home = pwd.getpwuid(os.getuid()).pw_dir
Ezio Melottice82d572013-05-09 15:19:45 +0300252 # $HOME can end with a trailing /, so strip it (see #17809)
Serhiy Storchakaa3fd0b22016-05-03 21:17:03 +0300253 home = home.rstrip("/") or '/'
254 self.assertEqual(posixpath.expanduser("~"), home)
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000255
Brett Cannonb47243a2003-06-16 21:54:50 +0000256 def test_normpath(self):
257 self.assertEqual(posixpath.normpath(""), ".")
258 self.assertEqual(posixpath.normpath("/"), "/")
259 self.assertEqual(posixpath.normpath("//"), "//")
260 self.assertEqual(posixpath.normpath("///"), "/")
261 self.assertEqual(posixpath.normpath("///foo/.//bar//"), "/foo/bar")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000262 self.assertEqual(posixpath.normpath("///foo/.//bar//.//..//.//baz"),
263 "/foo/baz")
Brett Cannonb47243a2003-06-16 21:54:50 +0000264 self.assertEqual(posixpath.normpath("///..//./foo/.//bar"), "/foo/bar")
265
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000266 self.assertEqual(posixpath.normpath(b""), b".")
267 self.assertEqual(posixpath.normpath(b"/"), b"/")
268 self.assertEqual(posixpath.normpath(b"//"), b"//")
269 self.assertEqual(posixpath.normpath(b"///"), b"/")
270 self.assertEqual(posixpath.normpath(b"///foo/.//bar//"), b"/foo/bar")
271 self.assertEqual(posixpath.normpath(b"///foo/.//bar//.//..//.//baz"),
272 b"/foo/baz")
273 self.assertEqual(posixpath.normpath(b"///..//./foo/.//bar"),
274 b"/foo/bar")
275
Serhiy Storchaka1548ed62013-02-18 13:32:30 +0200276 @skip_if_ABSTFN_contains_backslash
Serhiy Storchaka467393d2013-02-18 12:21:04 +0200277 def test_realpath_curdir(self):
278 self.assertEqual(realpath('.'), os.getcwd())
279 self.assertEqual(realpath('./.'), os.getcwd())
280 self.assertEqual(realpath('/'.join(['.'] * 100)), os.getcwd())
281
282 self.assertEqual(realpath(b'.'), os.getcwdb())
283 self.assertEqual(realpath(b'./.'), os.getcwdb())
284 self.assertEqual(realpath(b'/'.join([b'.'] * 100)), os.getcwdb())
285
Serhiy Storchaka1548ed62013-02-18 13:32:30 +0200286 @skip_if_ABSTFN_contains_backslash
Serhiy Storchaka467393d2013-02-18 12:21:04 +0200287 def test_realpath_pardir(self):
288 self.assertEqual(realpath('..'), dirname(os.getcwd()))
289 self.assertEqual(realpath('../..'), dirname(dirname(os.getcwd())))
290 self.assertEqual(realpath('/'.join(['..'] * 100)), '/')
291
292 self.assertEqual(realpath(b'..'), dirname(os.getcwdb()))
293 self.assertEqual(realpath(b'../..'), dirname(dirname(os.getcwdb())))
294 self.assertEqual(realpath(b'/'.join([b'..'] * 100)), b'/')
295
Brian Curtin52173d42010-12-02 18:29:18 +0000296 @unittest.skipUnless(hasattr(os, "symlink"),
297 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000298 @skip_if_ABSTFN_contains_backslash
299 def test_realpath_basic(self):
300 # Basic operation.
301 try:
302 os.symlink(ABSTFN+"1", ABSTFN)
303 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
304 finally:
305 support.unlink(ABSTFN)
Tim Petersa45cacf2004-08-20 03:47:14 +0000306
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
Michael Foord07926f02011-03-16 17:19:16 -0400310 def test_realpath_relative(self):
311 try:
312 os.symlink(posixpath.relpath(ABSTFN+"1"), ABSTFN)
313 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
314 finally:
315 support.unlink(ABSTFN)
316
317 @unittest.skipUnless(hasattr(os, "symlink"),
318 "Missing symlink implementation")
319 @skip_if_ABSTFN_contains_backslash
Brian Curtind40e6f72010-07-08 21:39:08 +0000320 def test_realpath_symlink_loops(self):
321 # Bug #930024, return the path unchanged if we get into an infinite
322 # symlink loop.
323 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000324 os.symlink(ABSTFN, ABSTFN)
325 self.assertEqual(realpath(ABSTFN), ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000326
Brian Curtind40e6f72010-07-08 21:39:08 +0000327 os.symlink(ABSTFN+"1", ABSTFN+"2")
328 os.symlink(ABSTFN+"2", ABSTFN+"1")
329 self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1")
330 self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000331
Serhiy Storchakadf326912013-02-10 12:22:07 +0200332 self.assertEqual(realpath(ABSTFN+"1/x"), ABSTFN+"1/x")
333 self.assertEqual(realpath(ABSTFN+"1/.."), dirname(ABSTFN))
334 self.assertEqual(realpath(ABSTFN+"1/../x"), dirname(ABSTFN) + "/x")
335 os.symlink(ABSTFN+"x", ABSTFN+"y")
336 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "y"),
337 ABSTFN + "y")
338 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "1"),
339 ABSTFN + "1")
340
341 os.symlink(basename(ABSTFN) + "a/b", ABSTFN+"a")
342 self.assertEqual(realpath(ABSTFN+"a"), ABSTFN+"a/b")
343
344 os.symlink("../" + basename(dirname(ABSTFN)) + "/" +
345 basename(ABSTFN) + "c", ABSTFN+"c")
346 self.assertEqual(realpath(ABSTFN+"c"), ABSTFN+"c")
347
Brian Curtind40e6f72010-07-08 21:39:08 +0000348 # Test using relative path as well.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300349 with support.change_cwd(dirname(ABSTFN)):
350 self.assertEqual(realpath(basename(ABSTFN)), ABSTFN)
Brian Curtind40e6f72010-07-08 21:39:08 +0000351 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000352 support.unlink(ABSTFN)
353 support.unlink(ABSTFN+"1")
354 support.unlink(ABSTFN+"2")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200355 support.unlink(ABSTFN+"y")
356 support.unlink(ABSTFN+"c")
Ezio Melotti136726c2013-03-01 20:59:17 +0200357 support.unlink(ABSTFN+"a")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200358
359 @unittest.skipUnless(hasattr(os, "symlink"),
360 "Missing symlink implementation")
361 @skip_if_ABSTFN_contains_backslash
362 def test_realpath_repeated_indirect_symlinks(self):
363 # Issue #6975.
364 try:
365 os.mkdir(ABSTFN)
366 os.symlink('../' + basename(ABSTFN), ABSTFN + '/self')
367 os.symlink('self/self/self', ABSTFN + '/link')
368 self.assertEqual(realpath(ABSTFN + '/link'), ABSTFN)
369 finally:
370 support.unlink(ABSTFN + '/self')
371 support.unlink(ABSTFN + '/link')
372 safe_rmdir(ABSTFN)
373
374 @unittest.skipUnless(hasattr(os, "symlink"),
375 "Missing symlink implementation")
376 @skip_if_ABSTFN_contains_backslash
377 def test_realpath_deep_recursion(self):
378 depth = 10
Serhiy Storchakadf326912013-02-10 12:22:07 +0200379 try:
380 os.mkdir(ABSTFN)
381 for i in range(depth):
382 os.symlink('/'.join(['%d' % i] * 10), ABSTFN + '/%d' % (i + 1))
383 os.symlink('.', ABSTFN + '/0')
384 self.assertEqual(realpath(ABSTFN + '/%d' % depth), ABSTFN)
385
386 # Test using relative path as well.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300387 with support.change_cwd(ABSTFN):
388 self.assertEqual(realpath('%d' % depth), ABSTFN)
Serhiy Storchakadf326912013-02-10 12:22:07 +0200389 finally:
Serhiy Storchakadf326912013-02-10 12:22:07 +0200390 for i in range(depth + 1):
391 support.unlink(ABSTFN + '/%d' % i)
392 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000393
Brian Curtin52173d42010-12-02 18:29:18 +0000394 @unittest.skipUnless(hasattr(os, "symlink"),
395 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000396 @skip_if_ABSTFN_contains_backslash
397 def test_realpath_resolve_parents(self):
398 # We also need to resolve any symlinks in the parents of a relative
399 # path passed to realpath. E.g.: current working directory is
400 # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call
401 # realpath("a"). This should return /usr/share/doc/a/.
402 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000403 os.mkdir(ABSTFN)
404 os.mkdir(ABSTFN + "/y")
405 os.symlink(ABSTFN + "/y", ABSTFN + "/k")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000406
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300407 with support.change_cwd(ABSTFN + "/k"):
408 self.assertEqual(realpath("a"), ABSTFN + "/y/a")
Brian Curtind40e6f72010-07-08 21:39:08 +0000409 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000410 support.unlink(ABSTFN + "/k")
411 safe_rmdir(ABSTFN + "/y")
412 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000413
Brian Curtin52173d42010-12-02 18:29:18 +0000414 @unittest.skipUnless(hasattr(os, "symlink"),
415 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000416 @skip_if_ABSTFN_contains_backslash
417 def test_realpath_resolve_before_normalizing(self):
418 # Bug #990669: Symbolic links should be resolved before we
419 # normalize the path. E.g.: if we have directories 'a', 'k' and 'y'
420 # in the following hierarchy:
421 # a/k/y
422 #
423 # and a symbolic link 'link-y' pointing to 'y' in directory 'a',
424 # then realpath("link-y/..") should return 'k', not 'a'.
425 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000426 os.mkdir(ABSTFN)
427 os.mkdir(ABSTFN + "/k")
428 os.mkdir(ABSTFN + "/k/y")
429 os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000430
Brian Curtind40e6f72010-07-08 21:39:08 +0000431 # Absolute path.
432 self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k")
433 # Relative path.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300434 with support.change_cwd(dirname(ABSTFN)):
435 self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."),
436 ABSTFN + "/k")
Brian Curtind40e6f72010-07-08 21:39:08 +0000437 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000438 support.unlink(ABSTFN + "/link-y")
439 safe_rmdir(ABSTFN + "/k/y")
440 safe_rmdir(ABSTFN + "/k")
441 safe_rmdir(ABSTFN)
Tim Peters5d36a552005-06-03 22:40:27 +0000442
Brian Curtin52173d42010-12-02 18:29:18 +0000443 @unittest.skipUnless(hasattr(os, "symlink"),
444 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000445 @skip_if_ABSTFN_contains_backslash
446 def test_realpath_resolve_first(self):
447 # Bug #1213894: The first component of the path, if not absolute,
448 # must be resolved too.
Georg Brandl268e61c2005-06-03 14:28:50 +0000449
Brian Curtind40e6f72010-07-08 21:39:08 +0000450 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000451 os.mkdir(ABSTFN)
452 os.mkdir(ABSTFN + "/k")
453 os.symlink(ABSTFN, ABSTFN + "link")
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300454 with support.change_cwd(dirname(ABSTFN)):
455 base = basename(ABSTFN)
456 self.assertEqual(realpath(base + "link"), ABSTFN)
457 self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k")
Brian Curtind40e6f72010-07-08 21:39:08 +0000458 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000459 support.unlink(ABSTFN + "link")
460 safe_rmdir(ABSTFN + "/k")
461 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000462
Guido van Rossumd8faa362007-04-27 19:54:29 +0000463 def test_relpath(self):
464 (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar")
465 try:
466 curdir = os.path.split(os.getcwd())[-1]
467 self.assertRaises(ValueError, posixpath.relpath, "")
468 self.assertEqual(posixpath.relpath("a"), "a")
469 self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a")
470 self.assertEqual(posixpath.relpath("a/b"), "a/b")
471 self.assertEqual(posixpath.relpath("../a/b"), "../a/b")
472 self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000473 self.assertEqual(posixpath.relpath("a/b", "../c"),
474 "../"+curdir+"/a/b")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000475 self.assertEqual(posixpath.relpath("a", "b/c"), "../../a")
Christian Heimesfaf2f632008-01-06 16:59:19 +0000476 self.assertEqual(posixpath.relpath("a", "a"), ".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000477 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x/y/z"), '../../../foo/bar/bat')
478 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/foo/bar"), 'bat')
479 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/"), 'foo/bar/bat')
480 self.assertEqual(posixpath.relpath("/", "/foo/bar/bat"), '../../..')
481 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x"), '../foo/bar/bat')
482 self.assertEqual(posixpath.relpath("/x", "/foo/bar/bat"), '../../../x')
483 self.assertEqual(posixpath.relpath("/", "/"), '.')
484 self.assertEqual(posixpath.relpath("/a", "/a"), '.')
485 self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000486 finally:
487 os.getcwd = real_getcwd
Brett Cannonb47243a2003-06-16 21:54:50 +0000488
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000489 def test_relpath_bytes(self):
490 (real_getcwdb, os.getcwdb) = (os.getcwdb, lambda: br"/home/user/bar")
491 try:
492 curdir = os.path.split(os.getcwdb())[-1]
493 self.assertRaises(ValueError, posixpath.relpath, b"")
494 self.assertEqual(posixpath.relpath(b"a"), b"a")
495 self.assertEqual(posixpath.relpath(posixpath.abspath(b"a")), b"a")
496 self.assertEqual(posixpath.relpath(b"a/b"), b"a/b")
497 self.assertEqual(posixpath.relpath(b"../a/b"), b"../a/b")
498 self.assertEqual(posixpath.relpath(b"a", b"../b"),
499 b"../"+curdir+b"/a")
500 self.assertEqual(posixpath.relpath(b"a/b", b"../c"),
501 b"../"+curdir+b"/a/b")
502 self.assertEqual(posixpath.relpath(b"a", b"b/c"), b"../../a")
503 self.assertEqual(posixpath.relpath(b"a", b"a"), b".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000504 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x/y/z"), b'../../../foo/bar/bat')
505 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/foo/bar"), b'bat')
506 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/"), b'foo/bar/bat')
507 self.assertEqual(posixpath.relpath(b"/", b"/foo/bar/bat"), b'../../..')
508 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x"), b'../foo/bar/bat')
509 self.assertEqual(posixpath.relpath(b"/x", b"/foo/bar/bat"), b'../../../x')
510 self.assertEqual(posixpath.relpath(b"/", b"/"), b'.')
511 self.assertEqual(posixpath.relpath(b"/a", b"/a"), b'.')
512 self.assertEqual(posixpath.relpath(b"/a/b", b"/a/b"), b'.')
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000513
514 self.assertRaises(TypeError, posixpath.relpath, b"bytes", "str")
515 self.assertRaises(TypeError, posixpath.relpath, "str", b"bytes")
516 finally:
517 os.getcwdb = real_getcwdb
518
Serhiy Storchaka38220932015-03-31 15:31:53 +0300519 def test_commonpath(self):
520 def check(paths, expected):
521 self.assertEqual(posixpath.commonpath(paths), expected)
522 self.assertEqual(posixpath.commonpath([os.fsencode(p) for p in paths]),
523 os.fsencode(expected))
524 def check_error(exc, paths):
525 self.assertRaises(exc, posixpath.commonpath, paths)
526 self.assertRaises(exc, posixpath.commonpath,
527 [os.fsencode(p) for p in paths])
528
529 self.assertRaises(ValueError, posixpath.commonpath, [])
530 check_error(ValueError, ['/usr', 'usr'])
531 check_error(ValueError, ['usr', '/usr'])
532
533 check(['/usr/local'], '/usr/local')
534 check(['/usr/local', '/usr/local'], '/usr/local')
535 check(['/usr/local/', '/usr/local'], '/usr/local')
536 check(['/usr/local/', '/usr/local/'], '/usr/local')
537 check(['/usr//local', '//usr/local'], '/usr/local')
538 check(['/usr/./local', '/./usr/local'], '/usr/local')
539 check(['/', '/dev'], '/')
540 check(['/usr', '/dev'], '/')
541 check(['/usr/lib/', '/usr/lib/python3'], '/usr/lib')
542 check(['/usr/lib/', '/usr/lib64/'], '/usr')
543
544 check(['/usr/lib', '/usr/lib64'], '/usr')
545 check(['/usr/lib/', '/usr/lib64'], '/usr')
546
547 check(['spam'], 'spam')
548 check(['spam', 'spam'], 'spam')
549 check(['spam', 'alot'], '')
550 check(['and/jam', 'and/spam'], 'and')
551 check(['and//jam', 'and/spam//'], 'and')
552 check(['and/./jam', './and/spam'], 'and')
553 check(['and/jam', 'and/spam', 'alot'], '')
554 check(['and/jam', 'and/spam', 'and'], 'and')
555
556 check([''], '')
557 check(['', 'spam/alot'], '')
558 check_error(ValueError, ['', '/spam/alot'])
559
560 self.assertRaises(TypeError, posixpath.commonpath,
561 [b'/usr/lib/', '/usr/lib/python3'])
562 self.assertRaises(TypeError, posixpath.commonpath,
563 [b'/usr/lib/', 'usr/lib/python3'])
564 self.assertRaises(TypeError, posixpath.commonpath,
565 [b'usr/lib/', '/usr/lib/python3'])
566 self.assertRaises(TypeError, posixpath.commonpath,
567 ['/usr/lib/', b'/usr/lib/python3'])
568 self.assertRaises(TypeError, posixpath.commonpath,
569 ['/usr/lib/', b'usr/lib/python3'])
570 self.assertRaises(TypeError, posixpath.commonpath,
571 ['usr/lib/', b'/usr/lib/python3'])
572
Florent Xiclunac9c79782010-03-08 12:24:53 +0000573
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200574class PosixCommonTest(test_genericpath.CommonTest, unittest.TestCase):
Florent Xiclunac9c79782010-03-08 12:24:53 +0000575 pathmodule = posixpath
576 attributes = ['relpath', 'samefile', 'sameopenfile', 'samestat']
577
578
Brett Cannonb47243a2003-06-16 21:54:50 +0000579if __name__=="__main__":
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200580 unittest.main()