blob: 9476ede5319397ddce5e76ce97a795a13ad2b6ce [file] [log] [blame]
Brian Curtind40e6f72010-07-08 21:39:08 +00001import os
Victor Stinner1ab6c2d2011-11-15 22:27:41 +01002import posixpath
Victor Stinner1ab6c2d2011-11-15 22:27:41 +01003import unittest
4import warnings
Georg Brandl89fad142010-03-14 10:23:39 +00005from posixpath import realpath, abspath, dirname, basename
Victor Stinner1ab6c2d2011-11-15 22:27:41 +01006from test import support, test_genericpath
Serhiy Storchakab21d1552018-03-02 11:53:51 +02007from test.support import FakePath
Johannes Gijsbers4ec40642004-08-14 15:01:53 +00008
Michael Foord07926f02011-03-16 17:19:16 -04009try:
10 import posix
11except ImportError:
12 posix = None
13
Johannes Gijsbers4ec40642004-08-14 15:01:53 +000014# An absolute path to a temporary filename for testing. We can't rely on TESTFN
15# being an absolute path, so we need this.
16
Benjamin Petersonee8712c2008-05-20 21:35:26 +000017ABSTFN = abspath(support.TESTFN)
Skip Montanaroe809b002000-07-12 00:20:08 +000018
Brian Curtind40e6f72010-07-08 21:39:08 +000019def skip_if_ABSTFN_contains_backslash(test):
20 """
21 On Windows, posixpath.abspath still returns paths with backslashes
22 instead of posix forward slashes. If this is the case, several tests
23 fail, so skip them.
24 """
25 found_backslash = '\\' in ABSTFN
26 msg = "ABSTFN is not a posix path - tests fail"
27 return [test, unittest.skip(msg)(test)][found_backslash]
28
Guido van Rossumd8faa362007-04-27 19:54:29 +000029def safe_rmdir(dirname):
30 try:
31 os.rmdir(dirname)
32 except OSError:
33 pass
34
Brett Cannonb47243a2003-06-16 21:54:50 +000035class PosixPathTest(unittest.TestCase):
Skip Montanaroe809b002000-07-12 00:20:08 +000036
Guido van Rossumd8faa362007-04-27 19:54:29 +000037 def setUp(self):
38 self.tearDown()
39
40 def tearDown(self):
41 for suffix in ["", "1", "2"]:
Benjamin Petersonee8712c2008-05-20 21:35:26 +000042 support.unlink(support.TESTFN + suffix)
43 safe_rmdir(support.TESTFN + suffix)
Guido van Rossumd8faa362007-04-27 19:54:29 +000044
Brett Cannonb47243a2003-06-16 21:54:50 +000045 def test_join(self):
Guido van Rossumf0af3e32008-10-02 18:55:37 +000046 self.assertEqual(posixpath.join("/foo", "bar", "/bar", "baz"),
47 "/bar/baz")
Brett Cannonb47243a2003-06-16 21:54:50 +000048 self.assertEqual(posixpath.join("/foo", "bar", "baz"), "/foo/bar/baz")
Guido van Rossumf0af3e32008-10-02 18:55:37 +000049 self.assertEqual(posixpath.join("/foo/", "bar/", "baz/"),
50 "/foo/bar/baz/")
51
52 self.assertEqual(posixpath.join(b"/foo", b"bar", b"/bar", b"baz"),
53 b"/bar/baz")
54 self.assertEqual(posixpath.join(b"/foo", b"bar", b"baz"),
55 b"/foo/bar/baz")
56 self.assertEqual(posixpath.join(b"/foo/", b"bar/", b"baz/"),
57 b"/foo/bar/baz/")
Skip Montanaroe809b002000-07-12 00:20:08 +000058
Brett Cannonb47243a2003-06-16 21:54:50 +000059 def test_split(self):
60 self.assertEqual(posixpath.split("/foo/bar"), ("/foo", "bar"))
61 self.assertEqual(posixpath.split("/"), ("/", ""))
62 self.assertEqual(posixpath.split("foo"), ("", "foo"))
63 self.assertEqual(posixpath.split("////foo"), ("////", "foo"))
64 self.assertEqual(posixpath.split("//foo//bar"), ("//foo", "bar"))
65
Guido van Rossumf0af3e32008-10-02 18:55:37 +000066 self.assertEqual(posixpath.split(b"/foo/bar"), (b"/foo", b"bar"))
67 self.assertEqual(posixpath.split(b"/"), (b"/", b""))
68 self.assertEqual(posixpath.split(b"foo"), (b"", b"foo"))
69 self.assertEqual(posixpath.split(b"////foo"), (b"////", b"foo"))
70 self.assertEqual(posixpath.split(b"//foo//bar"), (b"//foo", b"bar"))
71
Guido van Rossumd8faa362007-04-27 19:54:29 +000072 def splitextTest(self, path, filename, ext):
73 self.assertEqual(posixpath.splitext(path), (filename, ext))
74 self.assertEqual(posixpath.splitext("/" + path), ("/" + filename, ext))
Guido van Rossumf0af3e32008-10-02 18:55:37 +000075 self.assertEqual(posixpath.splitext("abc/" + path),
76 ("abc/" + filename, ext))
77 self.assertEqual(posixpath.splitext("abc.def/" + path),
78 ("abc.def/" + filename, ext))
79 self.assertEqual(posixpath.splitext("/abc.def/" + path),
80 ("/abc.def/" + filename, ext))
81 self.assertEqual(posixpath.splitext(path + "/"),
82 (filename + ext + "/", ""))
83
84 path = bytes(path, "ASCII")
85 filename = bytes(filename, "ASCII")
86 ext = bytes(ext, "ASCII")
87
88 self.assertEqual(posixpath.splitext(path), (filename, ext))
89 self.assertEqual(posixpath.splitext(b"/" + path),
90 (b"/" + filename, ext))
91 self.assertEqual(posixpath.splitext(b"abc/" + path),
92 (b"abc/" + filename, ext))
93 self.assertEqual(posixpath.splitext(b"abc.def/" + path),
94 (b"abc.def/" + filename, ext))
95 self.assertEqual(posixpath.splitext(b"/abc.def/" + path),
96 (b"/abc.def/" + filename, ext))
97 self.assertEqual(posixpath.splitext(path + b"/"),
98 (filename + ext + b"/", b""))
Brett Cannonb47243a2003-06-16 21:54:50 +000099
Guido van Rossumd8faa362007-04-27 19:54:29 +0000100 def test_splitext(self):
101 self.splitextTest("foo.bar", "foo", ".bar")
102 self.splitextTest("foo.boo.bar", "foo.boo", ".bar")
103 self.splitextTest("foo.boo.biff.bar", "foo.boo.biff", ".bar")
104 self.splitextTest(".csh.rc", ".csh", ".rc")
105 self.splitextTest("nodots", "nodots", "")
106 self.splitextTest(".cshrc", ".cshrc", "")
107 self.splitextTest("...manydots", "...manydots", "")
108 self.splitextTest("...manydots.ext", "...manydots", ".ext")
109 self.splitextTest(".", ".", "")
110 self.splitextTest("..", "..", "")
111 self.splitextTest("........", "........", "")
112 self.splitextTest("", "", "")
Brett Cannonb47243a2003-06-16 21:54:50 +0000113
114 def test_isabs(self):
115 self.assertIs(posixpath.isabs(""), False)
116 self.assertIs(posixpath.isabs("/"), True)
117 self.assertIs(posixpath.isabs("/foo"), True)
118 self.assertIs(posixpath.isabs("/foo/bar"), True)
119 self.assertIs(posixpath.isabs("foo/bar"), False)
120
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000121 self.assertIs(posixpath.isabs(b""), False)
122 self.assertIs(posixpath.isabs(b"/"), True)
123 self.assertIs(posixpath.isabs(b"/foo"), True)
124 self.assertIs(posixpath.isabs(b"/foo/bar"), True)
125 self.assertIs(posixpath.isabs(b"foo/bar"), False)
126
Brett Cannonb47243a2003-06-16 21:54:50 +0000127 def test_basename(self):
128 self.assertEqual(posixpath.basename("/foo/bar"), "bar")
129 self.assertEqual(posixpath.basename("/"), "")
130 self.assertEqual(posixpath.basename("foo"), "foo")
131 self.assertEqual(posixpath.basename("////foo"), "foo")
132 self.assertEqual(posixpath.basename("//foo//bar"), "bar")
133
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000134 self.assertEqual(posixpath.basename(b"/foo/bar"), b"bar")
135 self.assertEqual(posixpath.basename(b"/"), b"")
136 self.assertEqual(posixpath.basename(b"foo"), b"foo")
137 self.assertEqual(posixpath.basename(b"////foo"), b"foo")
138 self.assertEqual(posixpath.basename(b"//foo//bar"), b"bar")
139
Brett Cannonb47243a2003-06-16 21:54:50 +0000140 def test_dirname(self):
141 self.assertEqual(posixpath.dirname("/foo/bar"), "/foo")
142 self.assertEqual(posixpath.dirname("/"), "/")
143 self.assertEqual(posixpath.dirname("foo"), "")
144 self.assertEqual(posixpath.dirname("////foo"), "////")
145 self.assertEqual(posixpath.dirname("//foo//bar"), "//foo")
146
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000147 self.assertEqual(posixpath.dirname(b"/foo/bar"), b"/foo")
148 self.assertEqual(posixpath.dirname(b"/"), b"/")
149 self.assertEqual(posixpath.dirname(b"foo"), b"")
150 self.assertEqual(posixpath.dirname(b"////foo"), b"////")
151 self.assertEqual(posixpath.dirname(b"//foo//bar"), b"//foo")
152
Brett Cannonb47243a2003-06-16 21:54:50 +0000153 def test_islink(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000154 self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
Michael Foord07926f02011-03-16 17:19:16 -0400155 self.assertIs(posixpath.lexists(support.TESTFN + "2"), False)
Serhiy Storchaka17a00882018-06-16 13:25:55 +0300156 with open(support.TESTFN + "1", "wb") as f:
Guido van Rossum7dcb8442007-08-27 23:26:56 +0000157 f.write(b"foo")
Serhiy Storchaka17a00882018-06-16 13:25:55 +0300158 self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
159 if support.can_symlink():
160 os.symlink(support.TESTFN + "1", support.TESTFN + "2")
161 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
162 os.remove(support.TESTFN + "1")
163 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
164 self.assertIs(posixpath.exists(support.TESTFN + "2"), False)
165 self.assertIs(posixpath.lexists(support.TESTFN + "2"), True)
Brett Cannonb47243a2003-06-16 21:54:50 +0000166
Brett Cannonb47243a2003-06-16 21:54:50 +0000167 def test_ismount(self):
168 self.assertIs(posixpath.ismount("/"), True)
Serhiy Storchaka17a00882018-06-16 13:25:55 +0300169 self.assertIs(posixpath.ismount(b"/"), True)
Michael Foord07926f02011-03-16 17:19:16 -0400170
171 def test_ismount_non_existent(self):
172 # Non-existent mountpoint.
173 self.assertIs(posixpath.ismount(ABSTFN), False)
174 try:
175 os.mkdir(ABSTFN)
176 self.assertIs(posixpath.ismount(ABSTFN), False)
177 finally:
178 safe_rmdir(ABSTFN)
179
180 @unittest.skipUnless(support.can_symlink(),
181 "Test requires symlink support")
182 def test_ismount_symlinks(self):
183 # Symlinks are never mountpoints.
184 try:
185 os.symlink("/", ABSTFN)
186 self.assertIs(posixpath.ismount(ABSTFN), False)
187 finally:
188 os.unlink(ABSTFN)
189
190 @unittest.skipIf(posix is None, "Test requires posix module")
191 def test_ismount_different_device(self):
192 # Simulate the path being on a different device from its parent by
193 # mocking out st_dev.
194 save_lstat = os.lstat
195 def fake_lstat(path):
196 st_ino = 0
197 st_dev = 0
198 if path == ABSTFN:
199 st_dev = 1
200 st_ino = 1
201 return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
202 try:
203 os.lstat = fake_lstat
204 self.assertIs(posixpath.ismount(ABSTFN), True)
205 finally:
206 os.lstat = save_lstat
Brett Cannonb47243a2003-06-16 21:54:50 +0000207
R David Murray750018b2016-08-18 21:27:48 -0400208 @unittest.skipIf(posix is None, "Test requires posix module")
209 def test_ismount_directory_not_readable(self):
210 # issue #2466: Simulate ismount run on a directory that is not
211 # readable, which used to return False.
212 save_lstat = os.lstat
213 def fake_lstat(path):
214 st_ino = 0
215 st_dev = 0
216 if path.startswith(ABSTFN) and path != ABSTFN:
217 # ismount tries to read something inside the ABSTFN directory;
218 # simulate this being forbidden (no read permission).
219 raise OSError("Fake [Errno 13] Permission denied")
220 if path == ABSTFN:
221 st_dev = 1
222 st_ino = 1
223 return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
224 try:
225 os.lstat = fake_lstat
226 self.assertIs(posixpath.ismount(ABSTFN), True)
227 finally:
228 os.lstat = save_lstat
229
Brett Cannonb47243a2003-06-16 21:54:50 +0000230 def test_expanduser(self):
231 self.assertEqual(posixpath.expanduser("foo"), "foo")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000232 self.assertEqual(posixpath.expanduser(b"foo"), b"foo")
Serhiy Storchakaa3fd0b22016-05-03 21:17:03 +0300233 with support.EnvironmentVarGuard() as env:
234 for home in '/', '', '//', '///':
235 with self.subTest(home=home):
236 env['HOME'] = home
237 self.assertEqual(posixpath.expanduser("~"), "/")
238 self.assertEqual(posixpath.expanduser("~/"), "/")
239 self.assertEqual(posixpath.expanduser("~/foo"), "/foo")
Brett Cannonb47243a2003-06-16 21:54:50 +0000240 try:
241 import pwd
242 except ImportError:
243 pass
244 else:
Ezio Melottie9615932010-01-24 19:26:24 +0000245 self.assertIsInstance(posixpath.expanduser("~/"), str)
246 self.assertIsInstance(posixpath.expanduser(b"~/"), bytes)
Neal Norwitz168e73d2003-07-01 03:33:31 +0000247 # if home directory == root directory, this test makes no sense
248 if posixpath.expanduser("~") != '/':
249 self.assertEqual(
250 posixpath.expanduser("~") + "/",
251 posixpath.expanduser("~/")
252 )
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000253 self.assertEqual(
254 posixpath.expanduser(b"~") + b"/",
255 posixpath.expanduser(b"~/")
256 )
Ezio Melottie9615932010-01-24 19:26:24 +0000257 self.assertIsInstance(posixpath.expanduser("~root/"), str)
258 self.assertIsInstance(posixpath.expanduser("~foo/"), str)
259 self.assertIsInstance(posixpath.expanduser(b"~root/"), bytes)
260 self.assertIsInstance(posixpath.expanduser(b"~foo/"), bytes)
Brett Cannonb47243a2003-06-16 21:54:50 +0000261
Hirokazu Yamamoto71959632009-04-27 01:44:28 +0000262 with support.EnvironmentVarGuard() as env:
Michael Foord07926f02011-03-16 17:19:16 -0400263 # expanduser should fall back to using the password database
264 del env['HOME']
265 home = pwd.getpwuid(os.getuid()).pw_dir
Ezio Melottice82d572013-05-09 15:19:45 +0300266 # $HOME can end with a trailing /, so strip it (see #17809)
Serhiy Storchakaa3fd0b22016-05-03 21:17:03 +0300267 home = home.rstrip("/") or '/'
268 self.assertEqual(posixpath.expanduser("~"), home)
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000269
Brett Cannonb47243a2003-06-16 21:54:50 +0000270 def test_normpath(self):
271 self.assertEqual(posixpath.normpath(""), ".")
272 self.assertEqual(posixpath.normpath("/"), "/")
273 self.assertEqual(posixpath.normpath("//"), "//")
274 self.assertEqual(posixpath.normpath("///"), "/")
275 self.assertEqual(posixpath.normpath("///foo/.//bar//"), "/foo/bar")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000276 self.assertEqual(posixpath.normpath("///foo/.//bar//.//..//.//baz"),
277 "/foo/baz")
Brett Cannonb47243a2003-06-16 21:54:50 +0000278 self.assertEqual(posixpath.normpath("///..//./foo/.//bar"), "/foo/bar")
279
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000280 self.assertEqual(posixpath.normpath(b""), b".")
281 self.assertEqual(posixpath.normpath(b"/"), b"/")
282 self.assertEqual(posixpath.normpath(b"//"), b"//")
283 self.assertEqual(posixpath.normpath(b"///"), b"/")
284 self.assertEqual(posixpath.normpath(b"///foo/.//bar//"), b"/foo/bar")
285 self.assertEqual(posixpath.normpath(b"///foo/.//bar//.//..//.//baz"),
286 b"/foo/baz")
287 self.assertEqual(posixpath.normpath(b"///..//./foo/.//bar"),
288 b"/foo/bar")
289
Serhiy Storchaka1548ed62013-02-18 13:32:30 +0200290 @skip_if_ABSTFN_contains_backslash
Serhiy Storchaka467393d2013-02-18 12:21:04 +0200291 def test_realpath_curdir(self):
292 self.assertEqual(realpath('.'), os.getcwd())
293 self.assertEqual(realpath('./.'), os.getcwd())
294 self.assertEqual(realpath('/'.join(['.'] * 100)), os.getcwd())
295
296 self.assertEqual(realpath(b'.'), os.getcwdb())
297 self.assertEqual(realpath(b'./.'), os.getcwdb())
298 self.assertEqual(realpath(b'/'.join([b'.'] * 100)), os.getcwdb())
299
Serhiy Storchaka1548ed62013-02-18 13:32:30 +0200300 @skip_if_ABSTFN_contains_backslash
Serhiy Storchaka467393d2013-02-18 12:21:04 +0200301 def test_realpath_pardir(self):
302 self.assertEqual(realpath('..'), dirname(os.getcwd()))
303 self.assertEqual(realpath('../..'), dirname(dirname(os.getcwd())))
304 self.assertEqual(realpath('/'.join(['..'] * 100)), '/')
305
306 self.assertEqual(realpath(b'..'), dirname(os.getcwdb()))
307 self.assertEqual(realpath(b'../..'), dirname(dirname(os.getcwdb())))
308 self.assertEqual(realpath(b'/'.join([b'..'] * 100)), b'/')
309
Brian Curtin52173d42010-12-02 18:29:18 +0000310 @unittest.skipUnless(hasattr(os, "symlink"),
311 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000312 @skip_if_ABSTFN_contains_backslash
313 def test_realpath_basic(self):
314 # Basic operation.
315 try:
316 os.symlink(ABSTFN+"1", ABSTFN)
317 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
318 finally:
319 support.unlink(ABSTFN)
Tim Petersa45cacf2004-08-20 03:47:14 +0000320
Brian Curtin52173d42010-12-02 18:29:18 +0000321 @unittest.skipUnless(hasattr(os, "symlink"),
322 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000323 @skip_if_ABSTFN_contains_backslash
Michael Foord07926f02011-03-16 17:19:16 -0400324 def test_realpath_relative(self):
325 try:
326 os.symlink(posixpath.relpath(ABSTFN+"1"), ABSTFN)
327 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
328 finally:
329 support.unlink(ABSTFN)
330
331 @unittest.skipUnless(hasattr(os, "symlink"),
332 "Missing symlink implementation")
333 @skip_if_ABSTFN_contains_backslash
Brian Curtind40e6f72010-07-08 21:39:08 +0000334 def test_realpath_symlink_loops(self):
335 # Bug #930024, return the path unchanged if we get into an infinite
336 # symlink loop.
337 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000338 os.symlink(ABSTFN, ABSTFN)
339 self.assertEqual(realpath(ABSTFN), ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000340
Brian Curtind40e6f72010-07-08 21:39:08 +0000341 os.symlink(ABSTFN+"1", ABSTFN+"2")
342 os.symlink(ABSTFN+"2", ABSTFN+"1")
343 self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1")
344 self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000345
Serhiy Storchakadf326912013-02-10 12:22:07 +0200346 self.assertEqual(realpath(ABSTFN+"1/x"), ABSTFN+"1/x")
347 self.assertEqual(realpath(ABSTFN+"1/.."), dirname(ABSTFN))
348 self.assertEqual(realpath(ABSTFN+"1/../x"), dirname(ABSTFN) + "/x")
349 os.symlink(ABSTFN+"x", ABSTFN+"y")
350 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "y"),
351 ABSTFN + "y")
352 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "1"),
353 ABSTFN + "1")
354
355 os.symlink(basename(ABSTFN) + "a/b", ABSTFN+"a")
356 self.assertEqual(realpath(ABSTFN+"a"), ABSTFN+"a/b")
357
358 os.symlink("../" + basename(dirname(ABSTFN)) + "/" +
359 basename(ABSTFN) + "c", ABSTFN+"c")
360 self.assertEqual(realpath(ABSTFN+"c"), ABSTFN+"c")
361
Brian Curtind40e6f72010-07-08 21:39:08 +0000362 # Test using relative path as well.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300363 with support.change_cwd(dirname(ABSTFN)):
364 self.assertEqual(realpath(basename(ABSTFN)), ABSTFN)
Brian Curtind40e6f72010-07-08 21:39:08 +0000365 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000366 support.unlink(ABSTFN)
367 support.unlink(ABSTFN+"1")
368 support.unlink(ABSTFN+"2")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200369 support.unlink(ABSTFN+"y")
370 support.unlink(ABSTFN+"c")
Ezio Melotti136726c2013-03-01 20:59:17 +0200371 support.unlink(ABSTFN+"a")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200372
373 @unittest.skipUnless(hasattr(os, "symlink"),
374 "Missing symlink implementation")
375 @skip_if_ABSTFN_contains_backslash
376 def test_realpath_repeated_indirect_symlinks(self):
377 # Issue #6975.
378 try:
379 os.mkdir(ABSTFN)
380 os.symlink('../' + basename(ABSTFN), ABSTFN + '/self')
381 os.symlink('self/self/self', ABSTFN + '/link')
382 self.assertEqual(realpath(ABSTFN + '/link'), ABSTFN)
383 finally:
384 support.unlink(ABSTFN + '/self')
385 support.unlink(ABSTFN + '/link')
386 safe_rmdir(ABSTFN)
387
388 @unittest.skipUnless(hasattr(os, "symlink"),
389 "Missing symlink implementation")
390 @skip_if_ABSTFN_contains_backslash
391 def test_realpath_deep_recursion(self):
392 depth = 10
Serhiy Storchakadf326912013-02-10 12:22:07 +0200393 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.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300401 with support.change_cwd(ABSTFN):
402 self.assertEqual(realpath('%d' % depth), ABSTFN)
Serhiy Storchakadf326912013-02-10 12:22:07 +0200403 finally:
Serhiy Storchakadf326912013-02-10 12:22:07 +0200404 for i in range(depth + 1):
405 support.unlink(ABSTFN + '/%d' % i)
406 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000407
Brian Curtin52173d42010-12-02 18:29:18 +0000408 @unittest.skipUnless(hasattr(os, "symlink"),
409 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000410 @skip_if_ABSTFN_contains_backslash
411 def test_realpath_resolve_parents(self):
412 # We also need to resolve any symlinks in the parents of a relative
413 # path passed to realpath. E.g.: current working directory is
414 # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call
415 # realpath("a"). This should return /usr/share/doc/a/.
416 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000417 os.mkdir(ABSTFN)
418 os.mkdir(ABSTFN + "/y")
419 os.symlink(ABSTFN + "/y", ABSTFN + "/k")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000420
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300421 with support.change_cwd(ABSTFN + "/k"):
422 self.assertEqual(realpath("a"), ABSTFN + "/y/a")
Brian Curtind40e6f72010-07-08 21:39:08 +0000423 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000424 support.unlink(ABSTFN + "/k")
425 safe_rmdir(ABSTFN + "/y")
426 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000427
Brian Curtin52173d42010-12-02 18:29:18 +0000428 @unittest.skipUnless(hasattr(os, "symlink"),
429 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000430 @skip_if_ABSTFN_contains_backslash
431 def test_realpath_resolve_before_normalizing(self):
432 # Bug #990669: Symbolic links should be resolved before we
433 # normalize the path. E.g.: if we have directories 'a', 'k' and 'y'
434 # in the following hierarchy:
435 # a/k/y
436 #
437 # and a symbolic link 'link-y' pointing to 'y' in directory 'a',
438 # then realpath("link-y/..") should return 'k', not 'a'.
439 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000440 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.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300448 with support.change_cwd(dirname(ABSTFN)):
449 self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."),
450 ABSTFN + "/k")
Brian Curtind40e6f72010-07-08 21:39:08 +0000451 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000452 support.unlink(ABSTFN + "/link-y")
453 safe_rmdir(ABSTFN + "/k/y")
454 safe_rmdir(ABSTFN + "/k")
455 safe_rmdir(ABSTFN)
Tim Peters5d36a552005-06-03 22:40:27 +0000456
Brian Curtin52173d42010-12-02 18:29:18 +0000457 @unittest.skipUnless(hasattr(os, "symlink"),
458 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000459 @skip_if_ABSTFN_contains_backslash
460 def test_realpath_resolve_first(self):
461 # Bug #1213894: The first component of the path, if not absolute,
462 # must be resolved too.
Georg Brandl268e61c2005-06-03 14:28:50 +0000463
Brian Curtind40e6f72010-07-08 21:39:08 +0000464 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000465 os.mkdir(ABSTFN)
466 os.mkdir(ABSTFN + "/k")
467 os.symlink(ABSTFN, ABSTFN + "link")
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300468 with support.change_cwd(dirname(ABSTFN)):
469 base = basename(ABSTFN)
470 self.assertEqual(realpath(base + "link"), ABSTFN)
471 self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k")
Brian Curtind40e6f72010-07-08 21:39:08 +0000472 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000473 support.unlink(ABSTFN + "link")
474 safe_rmdir(ABSTFN + "/k")
475 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000476
Guido van Rossumd8faa362007-04-27 19:54:29 +0000477 def test_relpath(self):
478 (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar")
479 try:
480 curdir = os.path.split(os.getcwd())[-1]
481 self.assertRaises(ValueError, posixpath.relpath, "")
482 self.assertEqual(posixpath.relpath("a"), "a")
483 self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a")
484 self.assertEqual(posixpath.relpath("a/b"), "a/b")
485 self.assertEqual(posixpath.relpath("../a/b"), "../a/b")
486 self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000487 self.assertEqual(posixpath.relpath("a/b", "../c"),
488 "../"+curdir+"/a/b")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000489 self.assertEqual(posixpath.relpath("a", "b/c"), "../../a")
Christian Heimesfaf2f632008-01-06 16:59:19 +0000490 self.assertEqual(posixpath.relpath("a", "a"), ".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000491 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x/y/z"), '../../../foo/bar/bat')
492 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/foo/bar"), 'bat')
493 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/"), 'foo/bar/bat')
494 self.assertEqual(posixpath.relpath("/", "/foo/bar/bat"), '../../..')
495 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x"), '../foo/bar/bat')
496 self.assertEqual(posixpath.relpath("/x", "/foo/bar/bat"), '../../../x')
497 self.assertEqual(posixpath.relpath("/", "/"), '.')
498 self.assertEqual(posixpath.relpath("/a", "/a"), '.')
499 self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000500 finally:
501 os.getcwd = real_getcwd
Brett Cannonb47243a2003-06-16 21:54:50 +0000502
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000503 def test_relpath_bytes(self):
504 (real_getcwdb, os.getcwdb) = (os.getcwdb, lambda: br"/home/user/bar")
505 try:
506 curdir = os.path.split(os.getcwdb())[-1]
507 self.assertRaises(ValueError, posixpath.relpath, b"")
508 self.assertEqual(posixpath.relpath(b"a"), b"a")
509 self.assertEqual(posixpath.relpath(posixpath.abspath(b"a")), b"a")
510 self.assertEqual(posixpath.relpath(b"a/b"), b"a/b")
511 self.assertEqual(posixpath.relpath(b"../a/b"), b"../a/b")
512 self.assertEqual(posixpath.relpath(b"a", b"../b"),
513 b"../"+curdir+b"/a")
514 self.assertEqual(posixpath.relpath(b"a/b", b"../c"),
515 b"../"+curdir+b"/a/b")
516 self.assertEqual(posixpath.relpath(b"a", b"b/c"), b"../../a")
517 self.assertEqual(posixpath.relpath(b"a", b"a"), b".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000518 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x/y/z"), b'../../../foo/bar/bat')
519 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/foo/bar"), b'bat')
520 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/"), b'foo/bar/bat')
521 self.assertEqual(posixpath.relpath(b"/", b"/foo/bar/bat"), b'../../..')
522 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x"), b'../foo/bar/bat')
523 self.assertEqual(posixpath.relpath(b"/x", b"/foo/bar/bat"), b'../../../x')
524 self.assertEqual(posixpath.relpath(b"/", b"/"), b'.')
525 self.assertEqual(posixpath.relpath(b"/a", b"/a"), b'.')
526 self.assertEqual(posixpath.relpath(b"/a/b", b"/a/b"), b'.')
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000527
528 self.assertRaises(TypeError, posixpath.relpath, b"bytes", "str")
529 self.assertRaises(TypeError, posixpath.relpath, "str", b"bytes")
530 finally:
531 os.getcwdb = real_getcwdb
532
Serhiy Storchaka38220932015-03-31 15:31:53 +0300533 def test_commonpath(self):
534 def check(paths, expected):
535 self.assertEqual(posixpath.commonpath(paths), expected)
536 self.assertEqual(posixpath.commonpath([os.fsencode(p) for p in paths]),
537 os.fsencode(expected))
538 def check_error(exc, paths):
539 self.assertRaises(exc, posixpath.commonpath, paths)
540 self.assertRaises(exc, posixpath.commonpath,
541 [os.fsencode(p) for p in paths])
542
543 self.assertRaises(ValueError, posixpath.commonpath, [])
544 check_error(ValueError, ['/usr', 'usr'])
545 check_error(ValueError, ['usr', '/usr'])
546
547 check(['/usr/local'], '/usr/local')
548 check(['/usr/local', '/usr/local'], '/usr/local')
549 check(['/usr/local/', '/usr/local'], '/usr/local')
550 check(['/usr/local/', '/usr/local/'], '/usr/local')
551 check(['/usr//local', '//usr/local'], '/usr/local')
552 check(['/usr/./local', '/./usr/local'], '/usr/local')
553 check(['/', '/dev'], '/')
554 check(['/usr', '/dev'], '/')
555 check(['/usr/lib/', '/usr/lib/python3'], '/usr/lib')
556 check(['/usr/lib/', '/usr/lib64/'], '/usr')
557
558 check(['/usr/lib', '/usr/lib64'], '/usr')
559 check(['/usr/lib/', '/usr/lib64'], '/usr')
560
561 check(['spam'], 'spam')
562 check(['spam', 'spam'], 'spam')
563 check(['spam', 'alot'], '')
564 check(['and/jam', 'and/spam'], 'and')
565 check(['and//jam', 'and/spam//'], 'and')
566 check(['and/./jam', './and/spam'], 'and')
567 check(['and/jam', 'and/spam', 'alot'], '')
568 check(['and/jam', 'and/spam', 'and'], 'and')
569
570 check([''], '')
571 check(['', 'spam/alot'], '')
572 check_error(ValueError, ['', '/spam/alot'])
573
574 self.assertRaises(TypeError, posixpath.commonpath,
575 [b'/usr/lib/', '/usr/lib/python3'])
576 self.assertRaises(TypeError, posixpath.commonpath,
577 [b'/usr/lib/', 'usr/lib/python3'])
578 self.assertRaises(TypeError, posixpath.commonpath,
579 [b'usr/lib/', '/usr/lib/python3'])
580 self.assertRaises(TypeError, posixpath.commonpath,
581 ['/usr/lib/', b'/usr/lib/python3'])
582 self.assertRaises(TypeError, posixpath.commonpath,
583 ['/usr/lib/', b'usr/lib/python3'])
584 self.assertRaises(TypeError, posixpath.commonpath,
585 ['usr/lib/', b'/usr/lib/python3'])
586
Florent Xiclunac9c79782010-03-08 12:24:53 +0000587
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200588class PosixCommonTest(test_genericpath.CommonTest, unittest.TestCase):
Florent Xiclunac9c79782010-03-08 12:24:53 +0000589 pathmodule = posixpath
590 attributes = ['relpath', 'samefile', 'sameopenfile', 'samestat']
591
592
Brett Cannon3f9183b2016-08-26 14:44:48 -0700593class PathLikeTests(unittest.TestCase):
594
595 path = posixpath
596
Brett Cannon3f9183b2016-08-26 14:44:48 -0700597 def setUp(self):
598 self.file_name = support.TESTFN.lower()
Serhiy Storchakab21d1552018-03-02 11:53:51 +0200599 self.file_path = FakePath(support.TESTFN)
Brett Cannon3f9183b2016-08-26 14:44:48 -0700600 self.addCleanup(support.unlink, self.file_name)
601 with open(self.file_name, 'xb', 0) as file:
602 file.write(b"test_posixpath.PathLikeTests")
603
604 def assertPathEqual(self, func):
605 self.assertEqual(func(self.file_path), func(self.file_name))
606
607 def test_path_normcase(self):
608 self.assertPathEqual(self.path.normcase)
609
610 def test_path_isabs(self):
611 self.assertPathEqual(self.path.isabs)
612
613 def test_path_join(self):
Serhiy Storchakab21d1552018-03-02 11:53:51 +0200614 self.assertEqual(self.path.join('a', FakePath('b'), 'c'),
Brett Cannon3f9183b2016-08-26 14:44:48 -0700615 self.path.join('a', 'b', 'c'))
616
617 def test_path_split(self):
618 self.assertPathEqual(self.path.split)
619
620 def test_path_splitext(self):
621 self.assertPathEqual(self.path.splitext)
622
623 def test_path_splitdrive(self):
624 self.assertPathEqual(self.path.splitdrive)
625
626 def test_path_basename(self):
627 self.assertPathEqual(self.path.basename)
628
629 def test_path_dirname(self):
630 self.assertPathEqual(self.path.dirname)
631
632 def test_path_islink(self):
633 self.assertPathEqual(self.path.islink)
634
635 def test_path_lexists(self):
636 self.assertPathEqual(self.path.lexists)
637
638 def test_path_ismount(self):
639 self.assertPathEqual(self.path.ismount)
640
641 def test_path_expanduser(self):
642 self.assertPathEqual(self.path.expanduser)
643
644 def test_path_expandvars(self):
645 self.assertPathEqual(self.path.expandvars)
646
647 def test_path_normpath(self):
648 self.assertPathEqual(self.path.normpath)
649
650 def test_path_abspath(self):
651 self.assertPathEqual(self.path.abspath)
652
653 def test_path_realpath(self):
654 self.assertPathEqual(self.path.realpath)
655
656 def test_path_relpath(self):
657 self.assertPathEqual(self.path.relpath)
658
659 def test_path_commonpath(self):
660 common_path = self.path.commonpath([self.file_path, self.file_name])
661 self.assertEqual(common_path, self.file_name)
662
663
Brett Cannonb47243a2003-06-16 21:54:50 +0000664if __name__=="__main__":
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200665 unittest.main()