blob: 96b267cd45fd9ae9f4293cff6384ea8a67a2637e [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
Miss Islington (bot)a13b6542018-03-02 02:17:51 -08007from 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)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000156 f = open(support.TESTFN + "1", "wb")
Brett Cannonb47243a2003-06-16 21:54:50 +0000157 try:
Guido van Rossum7dcb8442007-08-27 23:26:56 +0000158 f.write(b"foo")
Brett Cannonb47243a2003-06-16 21:54:50 +0000159 f.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000160 self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
Brian Curtin3b4499c2010-12-28 14:31:47 +0000161 if support.can_symlink():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000162 os.symlink(support.TESTFN + "1", support.TESTFN + "2")
163 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
164 os.remove(support.TESTFN + "1")
165 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
166 self.assertIs(posixpath.exists(support.TESTFN + "2"), False)
167 self.assertIs(posixpath.lexists(support.TESTFN + "2"), True)
Brett Cannonb47243a2003-06-16 21:54:50 +0000168 finally:
169 if not f.close():
170 f.close()
Brett Cannonb47243a2003-06-16 21:54:50 +0000171
Brett Cannonb47243a2003-06-16 21:54:50 +0000172 def test_ismount(self):
173 self.assertIs(posixpath.ismount("/"), True)
Victor Stinner1ab6c2d2011-11-15 22:27:41 +0100174 with warnings.catch_warnings():
175 warnings.simplefilter("ignore", DeprecationWarning)
176 self.assertIs(posixpath.ismount(b"/"), True)
Michael Foord07926f02011-03-16 17:19:16 -0400177
178 def test_ismount_non_existent(self):
179 # Non-existent mountpoint.
180 self.assertIs(posixpath.ismount(ABSTFN), False)
181 try:
182 os.mkdir(ABSTFN)
183 self.assertIs(posixpath.ismount(ABSTFN), False)
184 finally:
185 safe_rmdir(ABSTFN)
186
187 @unittest.skipUnless(support.can_symlink(),
188 "Test requires symlink support")
189 def test_ismount_symlinks(self):
190 # Symlinks are never mountpoints.
191 try:
192 os.symlink("/", ABSTFN)
193 self.assertIs(posixpath.ismount(ABSTFN), False)
194 finally:
195 os.unlink(ABSTFN)
196
197 @unittest.skipIf(posix is None, "Test requires posix module")
198 def test_ismount_different_device(self):
199 # Simulate the path being on a different device from its parent by
200 # mocking out st_dev.
201 save_lstat = os.lstat
202 def fake_lstat(path):
203 st_ino = 0
204 st_dev = 0
205 if path == ABSTFN:
206 st_dev = 1
207 st_ino = 1
208 return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
209 try:
210 os.lstat = fake_lstat
211 self.assertIs(posixpath.ismount(ABSTFN), True)
212 finally:
213 os.lstat = save_lstat
Brett Cannonb47243a2003-06-16 21:54:50 +0000214
R David Murray750018b2016-08-18 21:27:48 -0400215 @unittest.skipIf(posix is None, "Test requires posix module")
216 def test_ismount_directory_not_readable(self):
217 # issue #2466: Simulate ismount run on a directory that is not
218 # readable, which used to return False.
219 save_lstat = os.lstat
220 def fake_lstat(path):
221 st_ino = 0
222 st_dev = 0
223 if path.startswith(ABSTFN) and path != ABSTFN:
224 # ismount tries to read something inside the ABSTFN directory;
225 # simulate this being forbidden (no read permission).
226 raise OSError("Fake [Errno 13] Permission denied")
227 if path == ABSTFN:
228 st_dev = 1
229 st_ino = 1
230 return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
231 try:
232 os.lstat = fake_lstat
233 self.assertIs(posixpath.ismount(ABSTFN), True)
234 finally:
235 os.lstat = save_lstat
236
Brett Cannonb47243a2003-06-16 21:54:50 +0000237 def test_expanduser(self):
238 self.assertEqual(posixpath.expanduser("foo"), "foo")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000239 self.assertEqual(posixpath.expanduser(b"foo"), b"foo")
Serhiy Storchakaa3fd0b22016-05-03 21:17:03 +0300240 with support.EnvironmentVarGuard() as env:
241 for home in '/', '', '//', '///':
242 with self.subTest(home=home):
243 env['HOME'] = home
244 self.assertEqual(posixpath.expanduser("~"), "/")
245 self.assertEqual(posixpath.expanduser("~/"), "/")
246 self.assertEqual(posixpath.expanduser("~/foo"), "/foo")
Brett Cannonb47243a2003-06-16 21:54:50 +0000247 try:
248 import pwd
249 except ImportError:
250 pass
251 else:
Ezio Melottie9615932010-01-24 19:26:24 +0000252 self.assertIsInstance(posixpath.expanduser("~/"), str)
253 self.assertIsInstance(posixpath.expanduser(b"~/"), bytes)
Neal Norwitz168e73d2003-07-01 03:33:31 +0000254 # if home directory == root directory, this test makes no sense
255 if posixpath.expanduser("~") != '/':
256 self.assertEqual(
257 posixpath.expanduser("~") + "/",
258 posixpath.expanduser("~/")
259 )
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000260 self.assertEqual(
261 posixpath.expanduser(b"~") + b"/",
262 posixpath.expanduser(b"~/")
263 )
Ezio Melottie9615932010-01-24 19:26:24 +0000264 self.assertIsInstance(posixpath.expanduser("~root/"), str)
265 self.assertIsInstance(posixpath.expanduser("~foo/"), str)
266 self.assertIsInstance(posixpath.expanduser(b"~root/"), bytes)
267 self.assertIsInstance(posixpath.expanduser(b"~foo/"), bytes)
Brett Cannonb47243a2003-06-16 21:54:50 +0000268
Hirokazu Yamamoto71959632009-04-27 01:44:28 +0000269 with support.EnvironmentVarGuard() as env:
Michael Foord07926f02011-03-16 17:19:16 -0400270 # expanduser should fall back to using the password database
271 del env['HOME']
272 home = pwd.getpwuid(os.getuid()).pw_dir
Ezio Melottice82d572013-05-09 15:19:45 +0300273 # $HOME can end with a trailing /, so strip it (see #17809)
Serhiy Storchakaa3fd0b22016-05-03 21:17:03 +0300274 home = home.rstrip("/") or '/'
275 self.assertEqual(posixpath.expanduser("~"), home)
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000276
Brett Cannonb47243a2003-06-16 21:54:50 +0000277 def test_normpath(self):
278 self.assertEqual(posixpath.normpath(""), ".")
279 self.assertEqual(posixpath.normpath("/"), "/")
280 self.assertEqual(posixpath.normpath("//"), "//")
281 self.assertEqual(posixpath.normpath("///"), "/")
282 self.assertEqual(posixpath.normpath("///foo/.//bar//"), "/foo/bar")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000283 self.assertEqual(posixpath.normpath("///foo/.//bar//.//..//.//baz"),
284 "/foo/baz")
Brett Cannonb47243a2003-06-16 21:54:50 +0000285 self.assertEqual(posixpath.normpath("///..//./foo/.//bar"), "/foo/bar")
286
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000287 self.assertEqual(posixpath.normpath(b""), b".")
288 self.assertEqual(posixpath.normpath(b"/"), b"/")
289 self.assertEqual(posixpath.normpath(b"//"), b"//")
290 self.assertEqual(posixpath.normpath(b"///"), b"/")
291 self.assertEqual(posixpath.normpath(b"///foo/.//bar//"), b"/foo/bar")
292 self.assertEqual(posixpath.normpath(b"///foo/.//bar//.//..//.//baz"),
293 b"/foo/baz")
294 self.assertEqual(posixpath.normpath(b"///..//./foo/.//bar"),
295 b"/foo/bar")
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_curdir(self):
299 self.assertEqual(realpath('.'), os.getcwd())
300 self.assertEqual(realpath('./.'), os.getcwd())
301 self.assertEqual(realpath('/'.join(['.'] * 100)), os.getcwd())
302
303 self.assertEqual(realpath(b'.'), os.getcwdb())
304 self.assertEqual(realpath(b'./.'), os.getcwdb())
305 self.assertEqual(realpath(b'/'.join([b'.'] * 100)), os.getcwdb())
306
Serhiy Storchaka1548ed62013-02-18 13:32:30 +0200307 @skip_if_ABSTFN_contains_backslash
Serhiy Storchaka467393d2013-02-18 12:21:04 +0200308 def test_realpath_pardir(self):
309 self.assertEqual(realpath('..'), dirname(os.getcwd()))
310 self.assertEqual(realpath('../..'), dirname(dirname(os.getcwd())))
311 self.assertEqual(realpath('/'.join(['..'] * 100)), '/')
312
313 self.assertEqual(realpath(b'..'), dirname(os.getcwdb()))
314 self.assertEqual(realpath(b'../..'), dirname(dirname(os.getcwdb())))
315 self.assertEqual(realpath(b'/'.join([b'..'] * 100)), b'/')
316
Brian Curtin52173d42010-12-02 18:29:18 +0000317 @unittest.skipUnless(hasattr(os, "symlink"),
318 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000319 @skip_if_ABSTFN_contains_backslash
320 def test_realpath_basic(self):
321 # Basic operation.
322 try:
323 os.symlink(ABSTFN+"1", ABSTFN)
324 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
325 finally:
326 support.unlink(ABSTFN)
Tim Petersa45cacf2004-08-20 03:47:14 +0000327
Brian Curtin52173d42010-12-02 18:29:18 +0000328 @unittest.skipUnless(hasattr(os, "symlink"),
329 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000330 @skip_if_ABSTFN_contains_backslash
Michael Foord07926f02011-03-16 17:19:16 -0400331 def test_realpath_relative(self):
332 try:
333 os.symlink(posixpath.relpath(ABSTFN+"1"), ABSTFN)
334 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
335 finally:
336 support.unlink(ABSTFN)
337
338 @unittest.skipUnless(hasattr(os, "symlink"),
339 "Missing symlink implementation")
340 @skip_if_ABSTFN_contains_backslash
Brian Curtind40e6f72010-07-08 21:39:08 +0000341 def test_realpath_symlink_loops(self):
342 # Bug #930024, return the path unchanged if we get into an infinite
343 # symlink loop.
344 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000345 os.symlink(ABSTFN, ABSTFN)
346 self.assertEqual(realpath(ABSTFN), ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000347
Brian Curtind40e6f72010-07-08 21:39:08 +0000348 os.symlink(ABSTFN+"1", ABSTFN+"2")
349 os.symlink(ABSTFN+"2", ABSTFN+"1")
350 self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1")
351 self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000352
Serhiy Storchakadf326912013-02-10 12:22:07 +0200353 self.assertEqual(realpath(ABSTFN+"1/x"), ABSTFN+"1/x")
354 self.assertEqual(realpath(ABSTFN+"1/.."), dirname(ABSTFN))
355 self.assertEqual(realpath(ABSTFN+"1/../x"), dirname(ABSTFN) + "/x")
356 os.symlink(ABSTFN+"x", ABSTFN+"y")
357 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "y"),
358 ABSTFN + "y")
359 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "1"),
360 ABSTFN + "1")
361
362 os.symlink(basename(ABSTFN) + "a/b", ABSTFN+"a")
363 self.assertEqual(realpath(ABSTFN+"a"), ABSTFN+"a/b")
364
365 os.symlink("../" + basename(dirname(ABSTFN)) + "/" +
366 basename(ABSTFN) + "c", ABSTFN+"c")
367 self.assertEqual(realpath(ABSTFN+"c"), ABSTFN+"c")
368
Brian Curtind40e6f72010-07-08 21:39:08 +0000369 # Test using relative path as well.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300370 with support.change_cwd(dirname(ABSTFN)):
371 self.assertEqual(realpath(basename(ABSTFN)), ABSTFN)
Brian Curtind40e6f72010-07-08 21:39:08 +0000372 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000373 support.unlink(ABSTFN)
374 support.unlink(ABSTFN+"1")
375 support.unlink(ABSTFN+"2")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200376 support.unlink(ABSTFN+"y")
377 support.unlink(ABSTFN+"c")
Ezio Melotti136726c2013-03-01 20:59:17 +0200378 support.unlink(ABSTFN+"a")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200379
380 @unittest.skipUnless(hasattr(os, "symlink"),
381 "Missing symlink implementation")
382 @skip_if_ABSTFN_contains_backslash
383 def test_realpath_repeated_indirect_symlinks(self):
384 # Issue #6975.
385 try:
386 os.mkdir(ABSTFN)
387 os.symlink('../' + basename(ABSTFN), ABSTFN + '/self')
388 os.symlink('self/self/self', ABSTFN + '/link')
389 self.assertEqual(realpath(ABSTFN + '/link'), ABSTFN)
390 finally:
391 support.unlink(ABSTFN + '/self')
392 support.unlink(ABSTFN + '/link')
393 safe_rmdir(ABSTFN)
394
395 @unittest.skipUnless(hasattr(os, "symlink"),
396 "Missing symlink implementation")
397 @skip_if_ABSTFN_contains_backslash
398 def test_realpath_deep_recursion(self):
399 depth = 10
Serhiy Storchakadf326912013-02-10 12:22:07 +0200400 try:
401 os.mkdir(ABSTFN)
402 for i in range(depth):
403 os.symlink('/'.join(['%d' % i] * 10), ABSTFN + '/%d' % (i + 1))
404 os.symlink('.', ABSTFN + '/0')
405 self.assertEqual(realpath(ABSTFN + '/%d' % depth), ABSTFN)
406
407 # Test using relative path as well.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300408 with support.change_cwd(ABSTFN):
409 self.assertEqual(realpath('%d' % depth), ABSTFN)
Serhiy Storchakadf326912013-02-10 12:22:07 +0200410 finally:
Serhiy Storchakadf326912013-02-10 12:22:07 +0200411 for i in range(depth + 1):
412 support.unlink(ABSTFN + '/%d' % i)
413 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000414
Brian Curtin52173d42010-12-02 18:29:18 +0000415 @unittest.skipUnless(hasattr(os, "symlink"),
416 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000417 @skip_if_ABSTFN_contains_backslash
418 def test_realpath_resolve_parents(self):
419 # We also need to resolve any symlinks in the parents of a relative
420 # path passed to realpath. E.g.: current working directory is
421 # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call
422 # realpath("a"). This should return /usr/share/doc/a/.
423 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000424 os.mkdir(ABSTFN)
425 os.mkdir(ABSTFN + "/y")
426 os.symlink(ABSTFN + "/y", ABSTFN + "/k")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000427
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300428 with support.change_cwd(ABSTFN + "/k"):
429 self.assertEqual(realpath("a"), ABSTFN + "/y/a")
Brian Curtind40e6f72010-07-08 21:39:08 +0000430 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000431 support.unlink(ABSTFN + "/k")
432 safe_rmdir(ABSTFN + "/y")
433 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000434
Brian Curtin52173d42010-12-02 18:29:18 +0000435 @unittest.skipUnless(hasattr(os, "symlink"),
436 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000437 @skip_if_ABSTFN_contains_backslash
438 def test_realpath_resolve_before_normalizing(self):
439 # Bug #990669: Symbolic links should be resolved before we
440 # normalize the path. E.g.: if we have directories 'a', 'k' and 'y'
441 # in the following hierarchy:
442 # a/k/y
443 #
444 # and a symbolic link 'link-y' pointing to 'y' in directory 'a',
445 # then realpath("link-y/..") should return 'k', not 'a'.
446 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000447 os.mkdir(ABSTFN)
448 os.mkdir(ABSTFN + "/k")
449 os.mkdir(ABSTFN + "/k/y")
450 os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000451
Brian Curtind40e6f72010-07-08 21:39:08 +0000452 # Absolute path.
453 self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k")
454 # Relative path.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300455 with support.change_cwd(dirname(ABSTFN)):
456 self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."),
457 ABSTFN + "/k")
Brian Curtind40e6f72010-07-08 21:39:08 +0000458 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000459 support.unlink(ABSTFN + "/link-y")
460 safe_rmdir(ABSTFN + "/k/y")
461 safe_rmdir(ABSTFN + "/k")
462 safe_rmdir(ABSTFN)
Tim Peters5d36a552005-06-03 22:40:27 +0000463
Brian Curtin52173d42010-12-02 18:29:18 +0000464 @unittest.skipUnless(hasattr(os, "symlink"),
465 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000466 @skip_if_ABSTFN_contains_backslash
467 def test_realpath_resolve_first(self):
468 # Bug #1213894: The first component of the path, if not absolute,
469 # must be resolved too.
Georg Brandl268e61c2005-06-03 14:28:50 +0000470
Brian Curtind40e6f72010-07-08 21:39:08 +0000471 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000472 os.mkdir(ABSTFN)
473 os.mkdir(ABSTFN + "/k")
474 os.symlink(ABSTFN, ABSTFN + "link")
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300475 with support.change_cwd(dirname(ABSTFN)):
476 base = basename(ABSTFN)
477 self.assertEqual(realpath(base + "link"), ABSTFN)
478 self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k")
Brian Curtind40e6f72010-07-08 21:39:08 +0000479 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000480 support.unlink(ABSTFN + "link")
481 safe_rmdir(ABSTFN + "/k")
482 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000483
Guido van Rossumd8faa362007-04-27 19:54:29 +0000484 def test_relpath(self):
485 (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar")
486 try:
487 curdir = os.path.split(os.getcwd())[-1]
488 self.assertRaises(ValueError, posixpath.relpath, "")
489 self.assertEqual(posixpath.relpath("a"), "a")
490 self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a")
491 self.assertEqual(posixpath.relpath("a/b"), "a/b")
492 self.assertEqual(posixpath.relpath("../a/b"), "../a/b")
493 self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000494 self.assertEqual(posixpath.relpath("a/b", "../c"),
495 "../"+curdir+"/a/b")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000496 self.assertEqual(posixpath.relpath("a", "b/c"), "../../a")
Christian Heimesfaf2f632008-01-06 16:59:19 +0000497 self.assertEqual(posixpath.relpath("a", "a"), ".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000498 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x/y/z"), '../../../foo/bar/bat')
499 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/foo/bar"), 'bat')
500 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/"), 'foo/bar/bat')
501 self.assertEqual(posixpath.relpath("/", "/foo/bar/bat"), '../../..')
502 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x"), '../foo/bar/bat')
503 self.assertEqual(posixpath.relpath("/x", "/foo/bar/bat"), '../../../x')
504 self.assertEqual(posixpath.relpath("/", "/"), '.')
505 self.assertEqual(posixpath.relpath("/a", "/a"), '.')
506 self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000507 finally:
508 os.getcwd = real_getcwd
Brett Cannonb47243a2003-06-16 21:54:50 +0000509
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000510 def test_relpath_bytes(self):
511 (real_getcwdb, os.getcwdb) = (os.getcwdb, lambda: br"/home/user/bar")
512 try:
513 curdir = os.path.split(os.getcwdb())[-1]
514 self.assertRaises(ValueError, posixpath.relpath, b"")
515 self.assertEqual(posixpath.relpath(b"a"), b"a")
516 self.assertEqual(posixpath.relpath(posixpath.abspath(b"a")), b"a")
517 self.assertEqual(posixpath.relpath(b"a/b"), b"a/b")
518 self.assertEqual(posixpath.relpath(b"../a/b"), b"../a/b")
519 self.assertEqual(posixpath.relpath(b"a", b"../b"),
520 b"../"+curdir+b"/a")
521 self.assertEqual(posixpath.relpath(b"a/b", b"../c"),
522 b"../"+curdir+b"/a/b")
523 self.assertEqual(posixpath.relpath(b"a", b"b/c"), b"../../a")
524 self.assertEqual(posixpath.relpath(b"a", b"a"), b".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000525 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x/y/z"), b'../../../foo/bar/bat')
526 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/foo/bar"), b'bat')
527 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/"), b'foo/bar/bat')
528 self.assertEqual(posixpath.relpath(b"/", b"/foo/bar/bat"), b'../../..')
529 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x"), b'../foo/bar/bat')
530 self.assertEqual(posixpath.relpath(b"/x", b"/foo/bar/bat"), b'../../../x')
531 self.assertEqual(posixpath.relpath(b"/", b"/"), b'.')
532 self.assertEqual(posixpath.relpath(b"/a", b"/a"), b'.')
533 self.assertEqual(posixpath.relpath(b"/a/b", b"/a/b"), b'.')
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000534
535 self.assertRaises(TypeError, posixpath.relpath, b"bytes", "str")
536 self.assertRaises(TypeError, posixpath.relpath, "str", b"bytes")
537 finally:
538 os.getcwdb = real_getcwdb
539
Serhiy Storchaka38220932015-03-31 15:31:53 +0300540 def test_commonpath(self):
541 def check(paths, expected):
542 self.assertEqual(posixpath.commonpath(paths), expected)
543 self.assertEqual(posixpath.commonpath([os.fsencode(p) for p in paths]),
544 os.fsencode(expected))
545 def check_error(exc, paths):
546 self.assertRaises(exc, posixpath.commonpath, paths)
547 self.assertRaises(exc, posixpath.commonpath,
548 [os.fsencode(p) for p in paths])
549
550 self.assertRaises(ValueError, posixpath.commonpath, [])
551 check_error(ValueError, ['/usr', 'usr'])
552 check_error(ValueError, ['usr', '/usr'])
553
554 check(['/usr/local'], '/usr/local')
555 check(['/usr/local', '/usr/local'], '/usr/local')
556 check(['/usr/local/', '/usr/local'], '/usr/local')
557 check(['/usr/local/', '/usr/local/'], '/usr/local')
558 check(['/usr//local', '//usr/local'], '/usr/local')
559 check(['/usr/./local', '/./usr/local'], '/usr/local')
560 check(['/', '/dev'], '/')
561 check(['/usr', '/dev'], '/')
562 check(['/usr/lib/', '/usr/lib/python3'], '/usr/lib')
563 check(['/usr/lib/', '/usr/lib64/'], '/usr')
564
565 check(['/usr/lib', '/usr/lib64'], '/usr')
566 check(['/usr/lib/', '/usr/lib64'], '/usr')
567
568 check(['spam'], 'spam')
569 check(['spam', 'spam'], 'spam')
570 check(['spam', 'alot'], '')
571 check(['and/jam', 'and/spam'], 'and')
572 check(['and//jam', 'and/spam//'], 'and')
573 check(['and/./jam', './and/spam'], 'and')
574 check(['and/jam', 'and/spam', 'alot'], '')
575 check(['and/jam', 'and/spam', 'and'], 'and')
576
577 check([''], '')
578 check(['', 'spam/alot'], '')
579 check_error(ValueError, ['', '/spam/alot'])
580
581 self.assertRaises(TypeError, posixpath.commonpath,
582 [b'/usr/lib/', '/usr/lib/python3'])
583 self.assertRaises(TypeError, posixpath.commonpath,
584 [b'/usr/lib/', 'usr/lib/python3'])
585 self.assertRaises(TypeError, posixpath.commonpath,
586 [b'usr/lib/', '/usr/lib/python3'])
587 self.assertRaises(TypeError, posixpath.commonpath,
588 ['/usr/lib/', b'/usr/lib/python3'])
589 self.assertRaises(TypeError, posixpath.commonpath,
590 ['/usr/lib/', b'usr/lib/python3'])
591 self.assertRaises(TypeError, posixpath.commonpath,
592 ['usr/lib/', b'/usr/lib/python3'])
593
Florent Xiclunac9c79782010-03-08 12:24:53 +0000594
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200595class PosixCommonTest(test_genericpath.CommonTest, unittest.TestCase):
Florent Xiclunac9c79782010-03-08 12:24:53 +0000596 pathmodule = posixpath
597 attributes = ['relpath', 'samefile', 'sameopenfile', 'samestat']
598
599
Brett Cannon3f9183b2016-08-26 14:44:48 -0700600class PathLikeTests(unittest.TestCase):
601
602 path = posixpath
603
Brett Cannon3f9183b2016-08-26 14:44:48 -0700604 def setUp(self):
605 self.file_name = support.TESTFN.lower()
Miss Islington (bot)a13b6542018-03-02 02:17:51 -0800606 self.file_path = FakePath(support.TESTFN)
Brett Cannon3f9183b2016-08-26 14:44:48 -0700607 self.addCleanup(support.unlink, self.file_name)
608 with open(self.file_name, 'xb', 0) as file:
609 file.write(b"test_posixpath.PathLikeTests")
610
611 def assertPathEqual(self, func):
612 self.assertEqual(func(self.file_path), func(self.file_name))
613
614 def test_path_normcase(self):
615 self.assertPathEqual(self.path.normcase)
616
617 def test_path_isabs(self):
618 self.assertPathEqual(self.path.isabs)
619
620 def test_path_join(self):
Miss Islington (bot)a13b6542018-03-02 02:17:51 -0800621 self.assertEqual(self.path.join('a', FakePath('b'), 'c'),
Brett Cannon3f9183b2016-08-26 14:44:48 -0700622 self.path.join('a', 'b', 'c'))
623
624 def test_path_split(self):
625 self.assertPathEqual(self.path.split)
626
627 def test_path_splitext(self):
628 self.assertPathEqual(self.path.splitext)
629
630 def test_path_splitdrive(self):
631 self.assertPathEqual(self.path.splitdrive)
632
633 def test_path_basename(self):
634 self.assertPathEqual(self.path.basename)
635
636 def test_path_dirname(self):
637 self.assertPathEqual(self.path.dirname)
638
639 def test_path_islink(self):
640 self.assertPathEqual(self.path.islink)
641
642 def test_path_lexists(self):
643 self.assertPathEqual(self.path.lexists)
644
645 def test_path_ismount(self):
646 self.assertPathEqual(self.path.ismount)
647
648 def test_path_expanduser(self):
649 self.assertPathEqual(self.path.expanduser)
650
651 def test_path_expandvars(self):
652 self.assertPathEqual(self.path.expandvars)
653
654 def test_path_normpath(self):
655 self.assertPathEqual(self.path.normpath)
656
657 def test_path_abspath(self):
658 self.assertPathEqual(self.path.abspath)
659
660 def test_path_realpath(self):
661 self.assertPathEqual(self.path.realpath)
662
663 def test_path_relpath(self):
664 self.assertPathEqual(self.path.relpath)
665
666 def test_path_commonpath(self):
667 common_path = self.path.commonpath([self.file_path, self.file_name])
668 self.assertEqual(common_path, self.file_name)
669
670
Brett Cannonb47243a2003-06-16 21:54:50 +0000671if __name__=="__main__":
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200672 unittest.main()