blob: 8a1e33b0c89997c2d7ed98b4aa35463724fbcf82 [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
Johannes Gijsbers4ec40642004-08-14 15:01:53 +00007
Michael Foord07926f02011-03-16 17:19:16 -04008try:
9 import posix
10except ImportError:
11 posix = None
12
Johannes Gijsbers4ec40642004-08-14 15:01:53 +000013# An absolute path to a temporary filename for testing. We can't rely on TESTFN
14# being an absolute path, so we need this.
15
Benjamin Petersonee8712c2008-05-20 21:35:26 +000016ABSTFN = abspath(support.TESTFN)
Skip Montanaroe809b002000-07-12 00:20:08 +000017
Brian Curtind40e6f72010-07-08 21:39:08 +000018def skip_if_ABSTFN_contains_backslash(test):
19 """
20 On Windows, posixpath.abspath still returns paths with backslashes
21 instead of posix forward slashes. If this is the case, several tests
22 fail, so skip them.
23 """
24 found_backslash = '\\' in ABSTFN
25 msg = "ABSTFN is not a posix path - tests fail"
26 return [test, unittest.skip(msg)(test)][found_backslash]
27
Guido van Rossumd8faa362007-04-27 19:54:29 +000028def safe_rmdir(dirname):
29 try:
30 os.rmdir(dirname)
31 except OSError:
32 pass
33
Brett Cannonb47243a2003-06-16 21:54:50 +000034class PosixPathTest(unittest.TestCase):
Skip Montanaroe809b002000-07-12 00:20:08 +000035
Guido van Rossumd8faa362007-04-27 19:54:29 +000036 def setUp(self):
37 self.tearDown()
38
39 def tearDown(self):
40 for suffix in ["", "1", "2"]:
Benjamin Petersonee8712c2008-05-20 21:35:26 +000041 support.unlink(support.TESTFN + suffix)
42 safe_rmdir(support.TESTFN + suffix)
Guido van Rossumd8faa362007-04-27 19:54:29 +000043
Brett Cannonb47243a2003-06-16 21:54:50 +000044 def test_join(self):
Guido van Rossumf0af3e32008-10-02 18:55:37 +000045 self.assertEqual(posixpath.join("/foo", "bar", "/bar", "baz"),
46 "/bar/baz")
Brett Cannonb47243a2003-06-16 21:54:50 +000047 self.assertEqual(posixpath.join("/foo", "bar", "baz"), "/foo/bar/baz")
Guido van Rossumf0af3e32008-10-02 18:55:37 +000048 self.assertEqual(posixpath.join("/foo/", "bar/", "baz/"),
49 "/foo/bar/baz/")
50
51 self.assertEqual(posixpath.join(b"/foo", b"bar", b"/bar", b"baz"),
52 b"/bar/baz")
53 self.assertEqual(posixpath.join(b"/foo", b"bar", b"baz"),
54 b"/foo/bar/baz")
55 self.assertEqual(posixpath.join(b"/foo/", b"bar/", b"baz/"),
56 b"/foo/bar/baz/")
Skip Montanaroe809b002000-07-12 00:20:08 +000057
Brett Cannonb47243a2003-06-16 21:54:50 +000058 def test_split(self):
59 self.assertEqual(posixpath.split("/foo/bar"), ("/foo", "bar"))
60 self.assertEqual(posixpath.split("/"), ("/", ""))
61 self.assertEqual(posixpath.split("foo"), ("", "foo"))
62 self.assertEqual(posixpath.split("////foo"), ("////", "foo"))
63 self.assertEqual(posixpath.split("//foo//bar"), ("//foo", "bar"))
64
Guido van Rossumf0af3e32008-10-02 18:55:37 +000065 self.assertEqual(posixpath.split(b"/foo/bar"), (b"/foo", b"bar"))
66 self.assertEqual(posixpath.split(b"/"), (b"/", b""))
67 self.assertEqual(posixpath.split(b"foo"), (b"", b"foo"))
68 self.assertEqual(posixpath.split(b"////foo"), (b"////", b"foo"))
69 self.assertEqual(posixpath.split(b"//foo//bar"), (b"//foo", b"bar"))
70
Guido van Rossumd8faa362007-04-27 19:54:29 +000071 def splitextTest(self, path, filename, ext):
72 self.assertEqual(posixpath.splitext(path), (filename, ext))
73 self.assertEqual(posixpath.splitext("/" + path), ("/" + filename, ext))
Guido van Rossumf0af3e32008-10-02 18:55:37 +000074 self.assertEqual(posixpath.splitext("abc/" + path),
75 ("abc/" + filename, ext))
76 self.assertEqual(posixpath.splitext("abc.def/" + path),
77 ("abc.def/" + filename, ext))
78 self.assertEqual(posixpath.splitext("/abc.def/" + path),
79 ("/abc.def/" + filename, ext))
80 self.assertEqual(posixpath.splitext(path + "/"),
81 (filename + ext + "/", ""))
82
83 path = bytes(path, "ASCII")
84 filename = bytes(filename, "ASCII")
85 ext = bytes(ext, "ASCII")
86
87 self.assertEqual(posixpath.splitext(path), (filename, ext))
88 self.assertEqual(posixpath.splitext(b"/" + path),
89 (b"/" + filename, ext))
90 self.assertEqual(posixpath.splitext(b"abc/" + path),
91 (b"abc/" + filename, ext))
92 self.assertEqual(posixpath.splitext(b"abc.def/" + path),
93 (b"abc.def/" + filename, ext))
94 self.assertEqual(posixpath.splitext(b"/abc.def/" + path),
95 (b"/abc.def/" + filename, ext))
96 self.assertEqual(posixpath.splitext(path + b"/"),
97 (filename + ext + b"/", b""))
Brett Cannonb47243a2003-06-16 21:54:50 +000098
Guido van Rossumd8faa362007-04-27 19:54:29 +000099 def test_splitext(self):
100 self.splitextTest("foo.bar", "foo", ".bar")
101 self.splitextTest("foo.boo.bar", "foo.boo", ".bar")
102 self.splitextTest("foo.boo.biff.bar", "foo.boo.biff", ".bar")
103 self.splitextTest(".csh.rc", ".csh", ".rc")
104 self.splitextTest("nodots", "nodots", "")
105 self.splitextTest(".cshrc", ".cshrc", "")
106 self.splitextTest("...manydots", "...manydots", "")
107 self.splitextTest("...manydots.ext", "...manydots", ".ext")
108 self.splitextTest(".", ".", "")
109 self.splitextTest("..", "..", "")
110 self.splitextTest("........", "........", "")
111 self.splitextTest("", "", "")
Brett Cannonb47243a2003-06-16 21:54:50 +0000112
113 def test_isabs(self):
114 self.assertIs(posixpath.isabs(""), False)
115 self.assertIs(posixpath.isabs("/"), True)
116 self.assertIs(posixpath.isabs("/foo"), True)
117 self.assertIs(posixpath.isabs("/foo/bar"), True)
118 self.assertIs(posixpath.isabs("foo/bar"), False)
119
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000120 self.assertIs(posixpath.isabs(b""), False)
121 self.assertIs(posixpath.isabs(b"/"), True)
122 self.assertIs(posixpath.isabs(b"/foo"), True)
123 self.assertIs(posixpath.isabs(b"/foo/bar"), True)
124 self.assertIs(posixpath.isabs(b"foo/bar"), False)
125
Brett Cannonb47243a2003-06-16 21:54:50 +0000126 def test_basename(self):
127 self.assertEqual(posixpath.basename("/foo/bar"), "bar")
128 self.assertEqual(posixpath.basename("/"), "")
129 self.assertEqual(posixpath.basename("foo"), "foo")
130 self.assertEqual(posixpath.basename("////foo"), "foo")
131 self.assertEqual(posixpath.basename("//foo//bar"), "bar")
132
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000133 self.assertEqual(posixpath.basename(b"/foo/bar"), b"bar")
134 self.assertEqual(posixpath.basename(b"/"), b"")
135 self.assertEqual(posixpath.basename(b"foo"), b"foo")
136 self.assertEqual(posixpath.basename(b"////foo"), b"foo")
137 self.assertEqual(posixpath.basename(b"//foo//bar"), b"bar")
138
Brett Cannonb47243a2003-06-16 21:54:50 +0000139 def test_dirname(self):
140 self.assertEqual(posixpath.dirname("/foo/bar"), "/foo")
141 self.assertEqual(posixpath.dirname("/"), "/")
142 self.assertEqual(posixpath.dirname("foo"), "")
143 self.assertEqual(posixpath.dirname("////foo"), "////")
144 self.assertEqual(posixpath.dirname("//foo//bar"), "//foo")
145
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000146 self.assertEqual(posixpath.dirname(b"/foo/bar"), b"/foo")
147 self.assertEqual(posixpath.dirname(b"/"), b"/")
148 self.assertEqual(posixpath.dirname(b"foo"), b"")
149 self.assertEqual(posixpath.dirname(b"////foo"), b"////")
150 self.assertEqual(posixpath.dirname(b"//foo//bar"), b"//foo")
151
Brett Cannonb47243a2003-06-16 21:54:50 +0000152 def test_islink(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000153 self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
Michael Foord07926f02011-03-16 17:19:16 -0400154 self.assertIs(posixpath.lexists(support.TESTFN + "2"), False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000155 f = open(support.TESTFN + "1", "wb")
Brett Cannonb47243a2003-06-16 21:54:50 +0000156 try:
Guido van Rossum7dcb8442007-08-27 23:26:56 +0000157 f.write(b"foo")
Brett Cannonb47243a2003-06-16 21:54:50 +0000158 f.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000159 self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
Brian Curtin3b4499c2010-12-28 14:31:47 +0000160 if support.can_symlink():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000161 os.symlink(support.TESTFN + "1", support.TESTFN + "2")
162 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
163 os.remove(support.TESTFN + "1")
164 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
165 self.assertIs(posixpath.exists(support.TESTFN + "2"), False)
166 self.assertIs(posixpath.lexists(support.TESTFN + "2"), True)
Brett Cannonb47243a2003-06-16 21:54:50 +0000167 finally:
168 if not f.close():
169 f.close()
Brett Cannonb47243a2003-06-16 21:54:50 +0000170
Brett Cannonb47243a2003-06-16 21:54:50 +0000171 def test_ismount(self):
172 self.assertIs(posixpath.ismount("/"), True)
Victor Stinner1ab6c2d2011-11-15 22:27:41 +0100173 with warnings.catch_warnings():
174 warnings.simplefilter("ignore", DeprecationWarning)
175 self.assertIs(posixpath.ismount(b"/"), True)
Michael Foord07926f02011-03-16 17:19:16 -0400176
177 def test_ismount_non_existent(self):
178 # Non-existent mountpoint.
179 self.assertIs(posixpath.ismount(ABSTFN), False)
180 try:
181 os.mkdir(ABSTFN)
182 self.assertIs(posixpath.ismount(ABSTFN), False)
183 finally:
184 safe_rmdir(ABSTFN)
185
186 @unittest.skipUnless(support.can_symlink(),
187 "Test requires symlink support")
188 def test_ismount_symlinks(self):
189 # Symlinks are never mountpoints.
190 try:
191 os.symlink("/", ABSTFN)
192 self.assertIs(posixpath.ismount(ABSTFN), False)
193 finally:
194 os.unlink(ABSTFN)
195
196 @unittest.skipIf(posix is None, "Test requires posix module")
197 def test_ismount_different_device(self):
198 # Simulate the path being on a different device from its parent by
199 # mocking out st_dev.
200 save_lstat = os.lstat
201 def fake_lstat(path):
202 st_ino = 0
203 st_dev = 0
204 if path == ABSTFN:
205 st_dev = 1
206 st_ino = 1
207 return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
208 try:
209 os.lstat = fake_lstat
210 self.assertIs(posixpath.ismount(ABSTFN), True)
211 finally:
212 os.lstat = save_lstat
Brett Cannonb47243a2003-06-16 21:54:50 +0000213
R David Murray750018b2016-08-18 21:27:48 -0400214 @unittest.skipIf(posix is None, "Test requires posix module")
215 def test_ismount_directory_not_readable(self):
216 # issue #2466: Simulate ismount run on a directory that is not
217 # readable, which used to return False.
218 save_lstat = os.lstat
219 def fake_lstat(path):
220 st_ino = 0
221 st_dev = 0
222 if path.startswith(ABSTFN) and path != ABSTFN:
223 # ismount tries to read something inside the ABSTFN directory;
224 # simulate this being forbidden (no read permission).
225 raise OSError("Fake [Errno 13] Permission denied")
226 if path == ABSTFN:
227 st_dev = 1
228 st_ino = 1
229 return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
230 try:
231 os.lstat = fake_lstat
232 self.assertIs(posixpath.ismount(ABSTFN), True)
233 finally:
234 os.lstat = save_lstat
235
Brett Cannonb47243a2003-06-16 21:54:50 +0000236 def test_expanduser(self):
237 self.assertEqual(posixpath.expanduser("foo"), "foo")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000238 self.assertEqual(posixpath.expanduser(b"foo"), b"foo")
Serhiy Storchakaa3fd0b22016-05-03 21:17:03 +0300239 with support.EnvironmentVarGuard() as env:
240 for home in '/', '', '//', '///':
241 with self.subTest(home=home):
242 env['HOME'] = home
243 self.assertEqual(posixpath.expanduser("~"), "/")
244 self.assertEqual(posixpath.expanduser("~/"), "/")
245 self.assertEqual(posixpath.expanduser("~/foo"), "/foo")
Brett Cannonb47243a2003-06-16 21:54:50 +0000246 try:
247 import pwd
248 except ImportError:
249 pass
250 else:
Ezio Melottie9615932010-01-24 19:26:24 +0000251 self.assertIsInstance(posixpath.expanduser("~/"), str)
252 self.assertIsInstance(posixpath.expanduser(b"~/"), bytes)
Neal Norwitz168e73d2003-07-01 03:33:31 +0000253 # if home directory == root directory, this test makes no sense
254 if posixpath.expanduser("~") != '/':
255 self.assertEqual(
256 posixpath.expanduser("~") + "/",
257 posixpath.expanduser("~/")
258 )
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000259 self.assertEqual(
260 posixpath.expanduser(b"~") + b"/",
261 posixpath.expanduser(b"~/")
262 )
Ezio Melottie9615932010-01-24 19:26:24 +0000263 self.assertIsInstance(posixpath.expanduser("~root/"), str)
264 self.assertIsInstance(posixpath.expanduser("~foo/"), str)
265 self.assertIsInstance(posixpath.expanduser(b"~root/"), bytes)
266 self.assertIsInstance(posixpath.expanduser(b"~foo/"), bytes)
Brett Cannonb47243a2003-06-16 21:54:50 +0000267
Hirokazu Yamamoto71959632009-04-27 01:44:28 +0000268 with support.EnvironmentVarGuard() as env:
Michael Foord07926f02011-03-16 17:19:16 -0400269 # expanduser should fall back to using the password database
270 del env['HOME']
271 home = pwd.getpwuid(os.getuid()).pw_dir
Ezio Melottice82d572013-05-09 15:19:45 +0300272 # $HOME can end with a trailing /, so strip it (see #17809)
Serhiy Storchakaa3fd0b22016-05-03 21:17:03 +0300273 home = home.rstrip("/") or '/'
274 self.assertEqual(posixpath.expanduser("~"), home)
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000275
Brett Cannonb47243a2003-06-16 21:54:50 +0000276 def test_normpath(self):
277 self.assertEqual(posixpath.normpath(""), ".")
278 self.assertEqual(posixpath.normpath("/"), "/")
279 self.assertEqual(posixpath.normpath("//"), "//")
280 self.assertEqual(posixpath.normpath("///"), "/")
281 self.assertEqual(posixpath.normpath("///foo/.//bar//"), "/foo/bar")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000282 self.assertEqual(posixpath.normpath("///foo/.//bar//.//..//.//baz"),
283 "/foo/baz")
Brett Cannonb47243a2003-06-16 21:54:50 +0000284 self.assertEqual(posixpath.normpath("///..//./foo/.//bar"), "/foo/bar")
285
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000286 self.assertEqual(posixpath.normpath(b""), b".")
287 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"///foo/.//bar//"), b"/foo/bar")
291 self.assertEqual(posixpath.normpath(b"///foo/.//bar//.//..//.//baz"),
292 b"/foo/baz")
293 self.assertEqual(posixpath.normpath(b"///..//./foo/.//bar"),
294 b"/foo/bar")
295
Serhiy Storchaka1548ed62013-02-18 13:32:30 +0200296 @skip_if_ABSTFN_contains_backslash
Serhiy Storchaka467393d2013-02-18 12:21:04 +0200297 def test_realpath_curdir(self):
298 self.assertEqual(realpath('.'), os.getcwd())
299 self.assertEqual(realpath('./.'), os.getcwd())
300 self.assertEqual(realpath('/'.join(['.'] * 100)), os.getcwd())
301
302 self.assertEqual(realpath(b'.'), os.getcwdb())
303 self.assertEqual(realpath(b'./.'), os.getcwdb())
304 self.assertEqual(realpath(b'/'.join([b'.'] * 100)), os.getcwdb())
305
Serhiy Storchaka1548ed62013-02-18 13:32:30 +0200306 @skip_if_ABSTFN_contains_backslash
Serhiy Storchaka467393d2013-02-18 12:21:04 +0200307 def test_realpath_pardir(self):
308 self.assertEqual(realpath('..'), dirname(os.getcwd()))
309 self.assertEqual(realpath('../..'), dirname(dirname(os.getcwd())))
310 self.assertEqual(realpath('/'.join(['..'] * 100)), '/')
311
312 self.assertEqual(realpath(b'..'), dirname(os.getcwdb()))
313 self.assertEqual(realpath(b'../..'), dirname(dirname(os.getcwdb())))
314 self.assertEqual(realpath(b'/'.join([b'..'] * 100)), b'/')
315
Brian Curtin52173d42010-12-02 18:29:18 +0000316 @unittest.skipUnless(hasattr(os, "symlink"),
317 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000318 @skip_if_ABSTFN_contains_backslash
319 def test_realpath_basic(self):
320 # Basic operation.
321 try:
322 os.symlink(ABSTFN+"1", ABSTFN)
323 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
324 finally:
325 support.unlink(ABSTFN)
Tim Petersa45cacf2004-08-20 03:47:14 +0000326
Brian Curtin52173d42010-12-02 18:29:18 +0000327 @unittest.skipUnless(hasattr(os, "symlink"),
328 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000329 @skip_if_ABSTFN_contains_backslash
Michael Foord07926f02011-03-16 17:19:16 -0400330 def test_realpath_relative(self):
331 try:
332 os.symlink(posixpath.relpath(ABSTFN+"1"), ABSTFN)
333 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
334 finally:
335 support.unlink(ABSTFN)
336
337 @unittest.skipUnless(hasattr(os, "symlink"),
338 "Missing symlink implementation")
339 @skip_if_ABSTFN_contains_backslash
Brian Curtind40e6f72010-07-08 21:39:08 +0000340 def test_realpath_symlink_loops(self):
341 # Bug #930024, return the path unchanged if we get into an infinite
342 # symlink loop.
343 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000344 os.symlink(ABSTFN, ABSTFN)
345 self.assertEqual(realpath(ABSTFN), ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000346
Brian Curtind40e6f72010-07-08 21:39:08 +0000347 os.symlink(ABSTFN+"1", ABSTFN+"2")
348 os.symlink(ABSTFN+"2", ABSTFN+"1")
349 self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1")
350 self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000351
Serhiy Storchakadf326912013-02-10 12:22:07 +0200352 self.assertEqual(realpath(ABSTFN+"1/x"), ABSTFN+"1/x")
353 self.assertEqual(realpath(ABSTFN+"1/.."), dirname(ABSTFN))
354 self.assertEqual(realpath(ABSTFN+"1/../x"), dirname(ABSTFN) + "/x")
355 os.symlink(ABSTFN+"x", ABSTFN+"y")
356 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "y"),
357 ABSTFN + "y")
358 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "1"),
359 ABSTFN + "1")
360
361 os.symlink(basename(ABSTFN) + "a/b", ABSTFN+"a")
362 self.assertEqual(realpath(ABSTFN+"a"), ABSTFN+"a/b")
363
364 os.symlink("../" + basename(dirname(ABSTFN)) + "/" +
365 basename(ABSTFN) + "c", ABSTFN+"c")
366 self.assertEqual(realpath(ABSTFN+"c"), ABSTFN+"c")
367
Brian Curtind40e6f72010-07-08 21:39:08 +0000368 # Test using relative path as well.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300369 with support.change_cwd(dirname(ABSTFN)):
370 self.assertEqual(realpath(basename(ABSTFN)), ABSTFN)
Brian Curtind40e6f72010-07-08 21:39:08 +0000371 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000372 support.unlink(ABSTFN)
373 support.unlink(ABSTFN+"1")
374 support.unlink(ABSTFN+"2")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200375 support.unlink(ABSTFN+"y")
376 support.unlink(ABSTFN+"c")
Ezio Melotti136726c2013-03-01 20:59:17 +0200377 support.unlink(ABSTFN+"a")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200378
379 @unittest.skipUnless(hasattr(os, "symlink"),
380 "Missing symlink implementation")
381 @skip_if_ABSTFN_contains_backslash
382 def test_realpath_repeated_indirect_symlinks(self):
383 # Issue #6975.
384 try:
385 os.mkdir(ABSTFN)
386 os.symlink('../' + basename(ABSTFN), ABSTFN + '/self')
387 os.symlink('self/self/self', ABSTFN + '/link')
388 self.assertEqual(realpath(ABSTFN + '/link'), ABSTFN)
389 finally:
390 support.unlink(ABSTFN + '/self')
391 support.unlink(ABSTFN + '/link')
392 safe_rmdir(ABSTFN)
393
394 @unittest.skipUnless(hasattr(os, "symlink"),
395 "Missing symlink implementation")
396 @skip_if_ABSTFN_contains_backslash
397 def test_realpath_deep_recursion(self):
398 depth = 10
Serhiy Storchakadf326912013-02-10 12:22:07 +0200399 try:
400 os.mkdir(ABSTFN)
401 for i in range(depth):
402 os.symlink('/'.join(['%d' % i] * 10), ABSTFN + '/%d' % (i + 1))
403 os.symlink('.', ABSTFN + '/0')
404 self.assertEqual(realpath(ABSTFN + '/%d' % depth), ABSTFN)
405
406 # Test using relative path as well.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300407 with support.change_cwd(ABSTFN):
408 self.assertEqual(realpath('%d' % depth), ABSTFN)
Serhiy Storchakadf326912013-02-10 12:22:07 +0200409 finally:
Serhiy Storchakadf326912013-02-10 12:22:07 +0200410 for i in range(depth + 1):
411 support.unlink(ABSTFN + '/%d' % i)
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_parents(self):
418 # We also need to resolve any symlinks in the parents of a relative
419 # path passed to realpath. E.g.: current working directory is
420 # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call
421 # realpath("a"). This should return /usr/share/doc/a/.
422 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000423 os.mkdir(ABSTFN)
424 os.mkdir(ABSTFN + "/y")
425 os.symlink(ABSTFN + "/y", ABSTFN + "/k")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000426
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300427 with support.change_cwd(ABSTFN + "/k"):
428 self.assertEqual(realpath("a"), ABSTFN + "/y/a")
Brian Curtind40e6f72010-07-08 21:39:08 +0000429 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000430 support.unlink(ABSTFN + "/k")
431 safe_rmdir(ABSTFN + "/y")
432 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000433
Brian Curtin52173d42010-12-02 18:29:18 +0000434 @unittest.skipUnless(hasattr(os, "symlink"),
435 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000436 @skip_if_ABSTFN_contains_backslash
437 def test_realpath_resolve_before_normalizing(self):
438 # Bug #990669: Symbolic links should be resolved before we
439 # normalize the path. E.g.: if we have directories 'a', 'k' and 'y'
440 # in the following hierarchy:
441 # a/k/y
442 #
443 # and a symbolic link 'link-y' pointing to 'y' in directory 'a',
444 # then realpath("link-y/..") should return 'k', not 'a'.
445 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000446 os.mkdir(ABSTFN)
447 os.mkdir(ABSTFN + "/k")
448 os.mkdir(ABSTFN + "/k/y")
449 os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000450
Brian Curtind40e6f72010-07-08 21:39:08 +0000451 # Absolute path.
452 self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k")
453 # Relative path.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300454 with support.change_cwd(dirname(ABSTFN)):
455 self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."),
456 ABSTFN + "/k")
Brian Curtind40e6f72010-07-08 21:39:08 +0000457 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000458 support.unlink(ABSTFN + "/link-y")
459 safe_rmdir(ABSTFN + "/k/y")
460 safe_rmdir(ABSTFN + "/k")
461 safe_rmdir(ABSTFN)
Tim Peters5d36a552005-06-03 22:40:27 +0000462
Brian Curtin52173d42010-12-02 18:29:18 +0000463 @unittest.skipUnless(hasattr(os, "symlink"),
464 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000465 @skip_if_ABSTFN_contains_backslash
466 def test_realpath_resolve_first(self):
467 # Bug #1213894: The first component of the path, if not absolute,
468 # must be resolved too.
Georg Brandl268e61c2005-06-03 14:28:50 +0000469
Brian Curtind40e6f72010-07-08 21:39:08 +0000470 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000471 os.mkdir(ABSTFN)
472 os.mkdir(ABSTFN + "/k")
473 os.symlink(ABSTFN, ABSTFN + "link")
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300474 with support.change_cwd(dirname(ABSTFN)):
475 base = basename(ABSTFN)
476 self.assertEqual(realpath(base + "link"), ABSTFN)
477 self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k")
Brian Curtind40e6f72010-07-08 21:39:08 +0000478 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000479 support.unlink(ABSTFN + "link")
480 safe_rmdir(ABSTFN + "/k")
481 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000482
Guido van Rossumd8faa362007-04-27 19:54:29 +0000483 def test_relpath(self):
484 (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar")
485 try:
486 curdir = os.path.split(os.getcwd())[-1]
487 self.assertRaises(ValueError, posixpath.relpath, "")
488 self.assertEqual(posixpath.relpath("a"), "a")
489 self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a")
490 self.assertEqual(posixpath.relpath("a/b"), "a/b")
491 self.assertEqual(posixpath.relpath("../a/b"), "../a/b")
492 self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000493 self.assertEqual(posixpath.relpath("a/b", "../c"),
494 "../"+curdir+"/a/b")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000495 self.assertEqual(posixpath.relpath("a", "b/c"), "../../a")
Christian Heimesfaf2f632008-01-06 16:59:19 +0000496 self.assertEqual(posixpath.relpath("a", "a"), ".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000497 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x/y/z"), '../../../foo/bar/bat')
498 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/foo/bar"), 'bat')
499 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/"), 'foo/bar/bat')
500 self.assertEqual(posixpath.relpath("/", "/foo/bar/bat"), '../../..')
501 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x"), '../foo/bar/bat')
502 self.assertEqual(posixpath.relpath("/x", "/foo/bar/bat"), '../../../x')
503 self.assertEqual(posixpath.relpath("/", "/"), '.')
504 self.assertEqual(posixpath.relpath("/a", "/a"), '.')
505 self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000506 finally:
507 os.getcwd = real_getcwd
Brett Cannonb47243a2003-06-16 21:54:50 +0000508
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000509 def test_relpath_bytes(self):
510 (real_getcwdb, os.getcwdb) = (os.getcwdb, lambda: br"/home/user/bar")
511 try:
512 curdir = os.path.split(os.getcwdb())[-1]
513 self.assertRaises(ValueError, posixpath.relpath, b"")
514 self.assertEqual(posixpath.relpath(b"a"), b"a")
515 self.assertEqual(posixpath.relpath(posixpath.abspath(b"a")), b"a")
516 self.assertEqual(posixpath.relpath(b"a/b"), b"a/b")
517 self.assertEqual(posixpath.relpath(b"../a/b"), b"../a/b")
518 self.assertEqual(posixpath.relpath(b"a", b"../b"),
519 b"../"+curdir+b"/a")
520 self.assertEqual(posixpath.relpath(b"a/b", b"../c"),
521 b"../"+curdir+b"/a/b")
522 self.assertEqual(posixpath.relpath(b"a", b"b/c"), b"../../a")
523 self.assertEqual(posixpath.relpath(b"a", b"a"), b".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000524 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x/y/z"), b'../../../foo/bar/bat')
525 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/foo/bar"), b'bat')
526 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/"), b'foo/bar/bat')
527 self.assertEqual(posixpath.relpath(b"/", b"/foo/bar/bat"), b'../../..')
528 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x"), b'../foo/bar/bat')
529 self.assertEqual(posixpath.relpath(b"/x", b"/foo/bar/bat"), b'../../../x')
530 self.assertEqual(posixpath.relpath(b"/", b"/"), b'.')
531 self.assertEqual(posixpath.relpath(b"/a", b"/a"), b'.')
532 self.assertEqual(posixpath.relpath(b"/a/b", b"/a/b"), b'.')
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000533
534 self.assertRaises(TypeError, posixpath.relpath, b"bytes", "str")
535 self.assertRaises(TypeError, posixpath.relpath, "str", b"bytes")
536 finally:
537 os.getcwdb = real_getcwdb
538
Serhiy Storchaka38220932015-03-31 15:31:53 +0300539 def test_commonpath(self):
540 def check(paths, expected):
541 self.assertEqual(posixpath.commonpath(paths), expected)
542 self.assertEqual(posixpath.commonpath([os.fsencode(p) for p in paths]),
543 os.fsencode(expected))
544 def check_error(exc, paths):
545 self.assertRaises(exc, posixpath.commonpath, paths)
546 self.assertRaises(exc, posixpath.commonpath,
547 [os.fsencode(p) for p in paths])
548
549 self.assertRaises(ValueError, posixpath.commonpath, [])
550 check_error(ValueError, ['/usr', 'usr'])
551 check_error(ValueError, ['usr', '/usr'])
552
553 check(['/usr/local'], '/usr/local')
554 check(['/usr/local', '/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(['/', '/dev'], '/')
560 check(['/usr', '/dev'], '/')
561 check(['/usr/lib/', '/usr/lib/python3'], '/usr/lib')
562 check(['/usr/lib/', '/usr/lib64/'], '/usr')
563
564 check(['/usr/lib', '/usr/lib64'], '/usr')
565 check(['/usr/lib/', '/usr/lib64'], '/usr')
566
567 check(['spam'], 'spam')
568 check(['spam', 'spam'], 'spam')
569 check(['spam', 'alot'], '')
570 check(['and/jam', 'and/spam'], 'and')
571 check(['and//jam', 'and/spam//'], 'and')
572 check(['and/./jam', './and/spam'], 'and')
573 check(['and/jam', 'and/spam', 'alot'], '')
574 check(['and/jam', 'and/spam', 'and'], 'and')
575
576 check([''], '')
577 check(['', 'spam/alot'], '')
578 check_error(ValueError, ['', '/spam/alot'])
579
580 self.assertRaises(TypeError, posixpath.commonpath,
581 [b'/usr/lib/', '/usr/lib/python3'])
582 self.assertRaises(TypeError, posixpath.commonpath,
583 [b'/usr/lib/', 'usr/lib/python3'])
584 self.assertRaises(TypeError, posixpath.commonpath,
585 [b'usr/lib/', '/usr/lib/python3'])
586 self.assertRaises(TypeError, posixpath.commonpath,
587 ['/usr/lib/', b'/usr/lib/python3'])
588 self.assertRaises(TypeError, posixpath.commonpath,
589 ['/usr/lib/', b'usr/lib/python3'])
590 self.assertRaises(TypeError, posixpath.commonpath,
591 ['usr/lib/', b'/usr/lib/python3'])
592
Florent Xiclunac9c79782010-03-08 12:24:53 +0000593
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200594class PosixCommonTest(test_genericpath.CommonTest, unittest.TestCase):
Florent Xiclunac9c79782010-03-08 12:24:53 +0000595 pathmodule = posixpath
596 attributes = ['relpath', 'samefile', 'sameopenfile', 'samestat']
597
598
Brett Cannon3f9183b2016-08-26 14:44:48 -0700599class PathLikeTests(unittest.TestCase):
600
601 path = posixpath
602
603 class PathLike:
604 def __init__(self, path=''):
605 self.path = path
606 def __fspath__(self):
607 if isinstance(self.path, BaseException):
608 raise self.path
609 else:
610 return self.path
611
612 def setUp(self):
613 self.file_name = support.TESTFN.lower()
614 self.file_path = self.PathLike(support.TESTFN)
615 self.addCleanup(support.unlink, self.file_name)
616 with open(self.file_name, 'xb', 0) as file:
617 file.write(b"test_posixpath.PathLikeTests")
618
619 def assertPathEqual(self, func):
620 self.assertEqual(func(self.file_path), func(self.file_name))
621
622 def test_path_normcase(self):
623 self.assertPathEqual(self.path.normcase)
624
625 def test_path_isabs(self):
626 self.assertPathEqual(self.path.isabs)
627
628 def test_path_join(self):
629 self.assertEqual(self.path.join('a', self.PathLike('b'), 'c'),
630 self.path.join('a', 'b', 'c'))
631
632 def test_path_split(self):
633 self.assertPathEqual(self.path.split)
634
635 def test_path_splitext(self):
636 self.assertPathEqual(self.path.splitext)
637
638 def test_path_splitdrive(self):
639 self.assertPathEqual(self.path.splitdrive)
640
641 def test_path_basename(self):
642 self.assertPathEqual(self.path.basename)
643
644 def test_path_dirname(self):
645 self.assertPathEqual(self.path.dirname)
646
647 def test_path_islink(self):
648 self.assertPathEqual(self.path.islink)
649
650 def test_path_lexists(self):
651 self.assertPathEqual(self.path.lexists)
652
653 def test_path_ismount(self):
654 self.assertPathEqual(self.path.ismount)
655
656 def test_path_expanduser(self):
657 self.assertPathEqual(self.path.expanduser)
658
659 def test_path_expandvars(self):
660 self.assertPathEqual(self.path.expandvars)
661
662 def test_path_normpath(self):
663 self.assertPathEqual(self.path.normpath)
664
665 def test_path_abspath(self):
666 self.assertPathEqual(self.path.abspath)
667
668 def test_path_realpath(self):
669 self.assertPathEqual(self.path.realpath)
670
671 def test_path_relpath(self):
672 self.assertPathEqual(self.path.relpath)
673
674 def test_path_commonpath(self):
675 common_path = self.path.commonpath([self.file_path, self.file_name])
676 self.assertEqual(common_path, self.file_name)
677
678
Brett Cannonb47243a2003-06-16 21:54:50 +0000679if __name__=="__main__":
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200680 unittest.main()