blob: e73b31cb648b227879587bd5b0b5019385380e5e [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
Miss Islington (bot)983d1ab2018-12-05 08:07:57 -08008from unittest import mock
Johannes Gijsbers4ec40642004-08-14 15:01:53 +00009
Michael Foord07926f02011-03-16 17:19:16 -040010try:
11 import posix
12except ImportError:
13 posix = None
14
Johannes Gijsbers4ec40642004-08-14 15:01:53 +000015# An absolute path to a temporary filename for testing. We can't rely on TESTFN
16# being an absolute path, so we need this.
17
Benjamin Petersonee8712c2008-05-20 21:35:26 +000018ABSTFN = abspath(support.TESTFN)
Skip Montanaroe809b002000-07-12 00:20:08 +000019
Brian Curtind40e6f72010-07-08 21:39:08 +000020def skip_if_ABSTFN_contains_backslash(test):
21 """
22 On Windows, posixpath.abspath still returns paths with backslashes
23 instead of posix forward slashes. If this is the case, several tests
24 fail, so skip them.
25 """
26 found_backslash = '\\' in ABSTFN
27 msg = "ABSTFN is not a posix path - tests fail"
28 return [test, unittest.skip(msg)(test)][found_backslash]
29
Guido van Rossumd8faa362007-04-27 19:54:29 +000030def safe_rmdir(dirname):
31 try:
32 os.rmdir(dirname)
33 except OSError:
34 pass
35
Brett Cannonb47243a2003-06-16 21:54:50 +000036class PosixPathTest(unittest.TestCase):
Skip Montanaroe809b002000-07-12 00:20:08 +000037
Guido van Rossumd8faa362007-04-27 19:54:29 +000038 def setUp(self):
39 self.tearDown()
40
41 def tearDown(self):
42 for suffix in ["", "1", "2"]:
Benjamin Petersonee8712c2008-05-20 21:35:26 +000043 support.unlink(support.TESTFN + suffix)
44 safe_rmdir(support.TESTFN + suffix)
Guido van Rossumd8faa362007-04-27 19:54:29 +000045
Brett Cannonb47243a2003-06-16 21:54:50 +000046 def test_join(self):
Guido van Rossumf0af3e32008-10-02 18:55:37 +000047 self.assertEqual(posixpath.join("/foo", "bar", "/bar", "baz"),
48 "/bar/baz")
Brett Cannonb47243a2003-06-16 21:54:50 +000049 self.assertEqual(posixpath.join("/foo", "bar", "baz"), "/foo/bar/baz")
Guido van Rossumf0af3e32008-10-02 18:55:37 +000050 self.assertEqual(posixpath.join("/foo/", "bar/", "baz/"),
51 "/foo/bar/baz/")
52
53 self.assertEqual(posixpath.join(b"/foo", b"bar", b"/bar", b"baz"),
54 b"/bar/baz")
55 self.assertEqual(posixpath.join(b"/foo", b"bar", b"baz"),
56 b"/foo/bar/baz")
57 self.assertEqual(posixpath.join(b"/foo/", b"bar/", b"baz/"),
58 b"/foo/bar/baz/")
Skip Montanaroe809b002000-07-12 00:20:08 +000059
Brett Cannonb47243a2003-06-16 21:54:50 +000060 def test_split(self):
61 self.assertEqual(posixpath.split("/foo/bar"), ("/foo", "bar"))
62 self.assertEqual(posixpath.split("/"), ("/", ""))
63 self.assertEqual(posixpath.split("foo"), ("", "foo"))
64 self.assertEqual(posixpath.split("////foo"), ("////", "foo"))
65 self.assertEqual(posixpath.split("//foo//bar"), ("//foo", "bar"))
66
Guido van Rossumf0af3e32008-10-02 18:55:37 +000067 self.assertEqual(posixpath.split(b"/foo/bar"), (b"/foo", b"bar"))
68 self.assertEqual(posixpath.split(b"/"), (b"/", b""))
69 self.assertEqual(posixpath.split(b"foo"), (b"", b"foo"))
70 self.assertEqual(posixpath.split(b"////foo"), (b"////", b"foo"))
71 self.assertEqual(posixpath.split(b"//foo//bar"), (b"//foo", b"bar"))
72
Guido van Rossumd8faa362007-04-27 19:54:29 +000073 def splitextTest(self, path, filename, ext):
74 self.assertEqual(posixpath.splitext(path), (filename, ext))
75 self.assertEqual(posixpath.splitext("/" + path), ("/" + filename, ext))
Guido van Rossumf0af3e32008-10-02 18:55:37 +000076 self.assertEqual(posixpath.splitext("abc/" + path),
77 ("abc/" + filename, ext))
78 self.assertEqual(posixpath.splitext("abc.def/" + path),
79 ("abc.def/" + filename, ext))
80 self.assertEqual(posixpath.splitext("/abc.def/" + path),
81 ("/abc.def/" + filename, ext))
82 self.assertEqual(posixpath.splitext(path + "/"),
83 (filename + ext + "/", ""))
84
85 path = bytes(path, "ASCII")
86 filename = bytes(filename, "ASCII")
87 ext = bytes(ext, "ASCII")
88
89 self.assertEqual(posixpath.splitext(path), (filename, ext))
90 self.assertEqual(posixpath.splitext(b"/" + path),
91 (b"/" + filename, ext))
92 self.assertEqual(posixpath.splitext(b"abc/" + path),
93 (b"abc/" + filename, ext))
94 self.assertEqual(posixpath.splitext(b"abc.def/" + path),
95 (b"abc.def/" + filename, ext))
96 self.assertEqual(posixpath.splitext(b"/abc.def/" + path),
97 (b"/abc.def/" + filename, ext))
98 self.assertEqual(posixpath.splitext(path + b"/"),
99 (filename + ext + b"/", b""))
Brett Cannonb47243a2003-06-16 21:54:50 +0000100
Guido van Rossumd8faa362007-04-27 19:54:29 +0000101 def test_splitext(self):
102 self.splitextTest("foo.bar", "foo", ".bar")
103 self.splitextTest("foo.boo.bar", "foo.boo", ".bar")
104 self.splitextTest("foo.boo.biff.bar", "foo.boo.biff", ".bar")
105 self.splitextTest(".csh.rc", ".csh", ".rc")
106 self.splitextTest("nodots", "nodots", "")
107 self.splitextTest(".cshrc", ".cshrc", "")
108 self.splitextTest("...manydots", "...manydots", "")
109 self.splitextTest("...manydots.ext", "...manydots", ".ext")
110 self.splitextTest(".", ".", "")
111 self.splitextTest("..", "..", "")
112 self.splitextTest("........", "........", "")
113 self.splitextTest("", "", "")
Brett Cannonb47243a2003-06-16 21:54:50 +0000114
115 def test_isabs(self):
116 self.assertIs(posixpath.isabs(""), False)
117 self.assertIs(posixpath.isabs("/"), True)
118 self.assertIs(posixpath.isabs("/foo"), True)
119 self.assertIs(posixpath.isabs("/foo/bar"), True)
120 self.assertIs(posixpath.isabs("foo/bar"), False)
121
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000122 self.assertIs(posixpath.isabs(b""), False)
123 self.assertIs(posixpath.isabs(b"/"), True)
124 self.assertIs(posixpath.isabs(b"/foo"), True)
125 self.assertIs(posixpath.isabs(b"/foo/bar"), True)
126 self.assertIs(posixpath.isabs(b"foo/bar"), False)
127
Brett Cannonb47243a2003-06-16 21:54:50 +0000128 def test_basename(self):
129 self.assertEqual(posixpath.basename("/foo/bar"), "bar")
130 self.assertEqual(posixpath.basename("/"), "")
131 self.assertEqual(posixpath.basename("foo"), "foo")
132 self.assertEqual(posixpath.basename("////foo"), "foo")
133 self.assertEqual(posixpath.basename("//foo//bar"), "bar")
134
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000135 self.assertEqual(posixpath.basename(b"/foo/bar"), b"bar")
136 self.assertEqual(posixpath.basename(b"/"), b"")
137 self.assertEqual(posixpath.basename(b"foo"), b"foo")
138 self.assertEqual(posixpath.basename(b"////foo"), b"foo")
139 self.assertEqual(posixpath.basename(b"//foo//bar"), b"bar")
140
Brett Cannonb47243a2003-06-16 21:54:50 +0000141 def test_dirname(self):
142 self.assertEqual(posixpath.dirname("/foo/bar"), "/foo")
143 self.assertEqual(posixpath.dirname("/"), "/")
144 self.assertEqual(posixpath.dirname("foo"), "")
145 self.assertEqual(posixpath.dirname("////foo"), "////")
146 self.assertEqual(posixpath.dirname("//foo//bar"), "//foo")
147
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000148 self.assertEqual(posixpath.dirname(b"/foo/bar"), b"/foo")
149 self.assertEqual(posixpath.dirname(b"/"), b"/")
150 self.assertEqual(posixpath.dirname(b"foo"), b"")
151 self.assertEqual(posixpath.dirname(b"////foo"), b"////")
152 self.assertEqual(posixpath.dirname(b"//foo//bar"), b"//foo")
153
Brett Cannonb47243a2003-06-16 21:54:50 +0000154 def test_islink(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000155 self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
Michael Foord07926f02011-03-16 17:19:16 -0400156 self.assertIs(posixpath.lexists(support.TESTFN + "2"), False)
Miss Islington (bot)63359332018-06-16 03:57:50 -0700157 with open(support.TESTFN + "1", "wb") as f:
Guido van Rossum7dcb8442007-08-27 23:26:56 +0000158 f.write(b"foo")
Miss Islington (bot)63359332018-06-16 03:57:50 -0700159 self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
160 if support.can_symlink():
161 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
Brett Cannonb47243a2003-06-16 21:54:50 +0000168 def test_ismount(self):
169 self.assertIs(posixpath.ismount("/"), True)
Miss Islington (bot)63359332018-06-16 03:57:50 -0700170 self.assertIs(posixpath.ismount(b"/"), True)
Michael Foord07926f02011-03-16 17:19:16 -0400171
172 def test_ismount_non_existent(self):
173 # Non-existent mountpoint.
174 self.assertIs(posixpath.ismount(ABSTFN), False)
175 try:
176 os.mkdir(ABSTFN)
177 self.assertIs(posixpath.ismount(ABSTFN), False)
178 finally:
179 safe_rmdir(ABSTFN)
180
181 @unittest.skipUnless(support.can_symlink(),
182 "Test requires symlink support")
183 def test_ismount_symlinks(self):
184 # Symlinks are never mountpoints.
185 try:
186 os.symlink("/", ABSTFN)
187 self.assertIs(posixpath.ismount(ABSTFN), False)
188 finally:
189 os.unlink(ABSTFN)
190
191 @unittest.skipIf(posix is None, "Test requires posix module")
192 def test_ismount_different_device(self):
193 # Simulate the path being on a different device from its parent by
194 # mocking out st_dev.
195 save_lstat = os.lstat
196 def fake_lstat(path):
197 st_ino = 0
198 st_dev = 0
199 if path == ABSTFN:
200 st_dev = 1
201 st_ino = 1
202 return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
203 try:
204 os.lstat = fake_lstat
205 self.assertIs(posixpath.ismount(ABSTFN), True)
206 finally:
207 os.lstat = save_lstat
Brett Cannonb47243a2003-06-16 21:54:50 +0000208
R David Murray750018b2016-08-18 21:27:48 -0400209 @unittest.skipIf(posix is None, "Test requires posix module")
210 def test_ismount_directory_not_readable(self):
211 # issue #2466: Simulate ismount run on a directory that is not
212 # readable, which used to return False.
213 save_lstat = os.lstat
214 def fake_lstat(path):
215 st_ino = 0
216 st_dev = 0
217 if path.startswith(ABSTFN) and path != ABSTFN:
218 # ismount tries to read something inside the ABSTFN directory;
219 # simulate this being forbidden (no read permission).
220 raise OSError("Fake [Errno 13] Permission denied")
221 if path == ABSTFN:
222 st_dev = 1
223 st_ino = 1
224 return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
225 try:
226 os.lstat = fake_lstat
227 self.assertIs(posixpath.ismount(ABSTFN), True)
228 finally:
229 os.lstat = save_lstat
230
Brett Cannonb47243a2003-06-16 21:54:50 +0000231 def test_expanduser(self):
232 self.assertEqual(posixpath.expanduser("foo"), "foo")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000233 self.assertEqual(posixpath.expanduser(b"foo"), b"foo")
Miss Islington (bot)983d1ab2018-12-05 08:07:57 -0800234
235 def test_expanduser_home_envvar(self):
Serhiy Storchakaa3fd0b22016-05-03 21:17:03 +0300236 with support.EnvironmentVarGuard() as env:
Miss Islington (bot)983d1ab2018-12-05 08:07:57 -0800237 env['HOME'] = '/home/victor'
238 self.assertEqual(posixpath.expanduser("~"), "/home/victor")
239
240 # expanduser() strips trailing slash
241 env['HOME'] = '/home/victor/'
242 self.assertEqual(posixpath.expanduser("~"), "/home/victor")
243
Serhiy Storchakaa3fd0b22016-05-03 21:17:03 +0300244 for home in '/', '', '//', '///':
245 with self.subTest(home=home):
246 env['HOME'] = home
247 self.assertEqual(posixpath.expanduser("~"), "/")
248 self.assertEqual(posixpath.expanduser("~/"), "/")
249 self.assertEqual(posixpath.expanduser("~/foo"), "/foo")
Brett Cannonb47243a2003-06-16 21:54:50 +0000250
Miss Islington (bot)983d1ab2018-12-05 08:07:57 -0800251 def test_expanduser_pwd(self):
252 pwd = support.import_module('pwd')
253
254 self.assertIsInstance(posixpath.expanduser("~/"), str)
255 self.assertIsInstance(posixpath.expanduser(b"~/"), bytes)
256
257 # if home directory == root directory, this test makes no sense
258 if posixpath.expanduser("~") != '/':
259 self.assertEqual(
260 posixpath.expanduser("~") + "/",
261 posixpath.expanduser("~/")
262 )
263 self.assertEqual(
264 posixpath.expanduser(b"~") + b"/",
265 posixpath.expanduser(b"~/")
266 )
267 self.assertIsInstance(posixpath.expanduser("~root/"), str)
268 self.assertIsInstance(posixpath.expanduser("~foo/"), str)
269 self.assertIsInstance(posixpath.expanduser(b"~root/"), bytes)
270 self.assertIsInstance(posixpath.expanduser(b"~foo/"), bytes)
271
272 with support.EnvironmentVarGuard() as env:
273 # expanduser should fall back to using the password database
274 del env['HOME']
275
276 home = pwd.getpwuid(os.getuid()).pw_dir
277 # $HOME can end with a trailing /, so strip it (see #17809)
278 home = home.rstrip("/") or '/'
279 self.assertEqual(posixpath.expanduser("~"), home)
280
281 # bpo-10496: If the HOME environment variable is not set and the
282 # user (current identifier or name in the path) doesn't exist in
283 # the password database (pwd.getuid() or pwd.getpwnam() fail),
284 # expanduser() must return the path unchanged.
285 with mock.patch.object(pwd, 'getpwuid', side_effect=KeyError), \
286 mock.patch.object(pwd, 'getpwnam', side_effect=KeyError):
287 for path in ('~', '~/.local', '~vstinner/'):
288 self.assertEqual(posixpath.expanduser(path), path)
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000289
Brett Cannonb47243a2003-06-16 21:54:50 +0000290 def test_normpath(self):
291 self.assertEqual(posixpath.normpath(""), ".")
292 self.assertEqual(posixpath.normpath("/"), "/")
293 self.assertEqual(posixpath.normpath("//"), "//")
294 self.assertEqual(posixpath.normpath("///"), "/")
295 self.assertEqual(posixpath.normpath("///foo/.//bar//"), "/foo/bar")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000296 self.assertEqual(posixpath.normpath("///foo/.//bar//.//..//.//baz"),
297 "/foo/baz")
Brett Cannonb47243a2003-06-16 21:54:50 +0000298 self.assertEqual(posixpath.normpath("///..//./foo/.//bar"), "/foo/bar")
299
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000300 self.assertEqual(posixpath.normpath(b""), b".")
301 self.assertEqual(posixpath.normpath(b"/"), b"/")
302 self.assertEqual(posixpath.normpath(b"//"), b"//")
303 self.assertEqual(posixpath.normpath(b"///"), b"/")
304 self.assertEqual(posixpath.normpath(b"///foo/.//bar//"), b"/foo/bar")
305 self.assertEqual(posixpath.normpath(b"///foo/.//bar//.//..//.//baz"),
306 b"/foo/baz")
307 self.assertEqual(posixpath.normpath(b"///..//./foo/.//bar"),
308 b"/foo/bar")
309
Serhiy Storchaka1548ed62013-02-18 13:32:30 +0200310 @skip_if_ABSTFN_contains_backslash
Serhiy Storchaka467393d2013-02-18 12:21:04 +0200311 def test_realpath_curdir(self):
312 self.assertEqual(realpath('.'), os.getcwd())
313 self.assertEqual(realpath('./.'), os.getcwd())
314 self.assertEqual(realpath('/'.join(['.'] * 100)), os.getcwd())
315
316 self.assertEqual(realpath(b'.'), os.getcwdb())
317 self.assertEqual(realpath(b'./.'), os.getcwdb())
318 self.assertEqual(realpath(b'/'.join([b'.'] * 100)), os.getcwdb())
319
Serhiy Storchaka1548ed62013-02-18 13:32:30 +0200320 @skip_if_ABSTFN_contains_backslash
Serhiy Storchaka467393d2013-02-18 12:21:04 +0200321 def test_realpath_pardir(self):
322 self.assertEqual(realpath('..'), dirname(os.getcwd()))
323 self.assertEqual(realpath('../..'), dirname(dirname(os.getcwd())))
324 self.assertEqual(realpath('/'.join(['..'] * 100)), '/')
325
326 self.assertEqual(realpath(b'..'), dirname(os.getcwdb()))
327 self.assertEqual(realpath(b'../..'), dirname(dirname(os.getcwdb())))
328 self.assertEqual(realpath(b'/'.join([b'..'] * 100)), b'/')
329
Brian Curtin52173d42010-12-02 18:29:18 +0000330 @unittest.skipUnless(hasattr(os, "symlink"),
331 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000332 @skip_if_ABSTFN_contains_backslash
333 def test_realpath_basic(self):
334 # Basic operation.
335 try:
336 os.symlink(ABSTFN+"1", ABSTFN)
337 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
338 finally:
339 support.unlink(ABSTFN)
Tim Petersa45cacf2004-08-20 03:47:14 +0000340
Brian Curtin52173d42010-12-02 18:29:18 +0000341 @unittest.skipUnless(hasattr(os, "symlink"),
342 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000343 @skip_if_ABSTFN_contains_backslash
Michael Foord07926f02011-03-16 17:19:16 -0400344 def test_realpath_relative(self):
345 try:
346 os.symlink(posixpath.relpath(ABSTFN+"1"), ABSTFN)
347 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
348 finally:
349 support.unlink(ABSTFN)
350
351 @unittest.skipUnless(hasattr(os, "symlink"),
352 "Missing symlink implementation")
353 @skip_if_ABSTFN_contains_backslash
Brian Curtind40e6f72010-07-08 21:39:08 +0000354 def test_realpath_symlink_loops(self):
355 # Bug #930024, return the path unchanged if we get into an infinite
356 # symlink loop.
357 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000358 os.symlink(ABSTFN, ABSTFN)
359 self.assertEqual(realpath(ABSTFN), ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000360
Brian Curtind40e6f72010-07-08 21:39:08 +0000361 os.symlink(ABSTFN+"1", ABSTFN+"2")
362 os.symlink(ABSTFN+"2", ABSTFN+"1")
363 self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1")
364 self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000365
Serhiy Storchakadf326912013-02-10 12:22:07 +0200366 self.assertEqual(realpath(ABSTFN+"1/x"), ABSTFN+"1/x")
367 self.assertEqual(realpath(ABSTFN+"1/.."), dirname(ABSTFN))
368 self.assertEqual(realpath(ABSTFN+"1/../x"), dirname(ABSTFN) + "/x")
369 os.symlink(ABSTFN+"x", ABSTFN+"y")
370 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "y"),
371 ABSTFN + "y")
372 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "1"),
373 ABSTFN + "1")
374
375 os.symlink(basename(ABSTFN) + "a/b", ABSTFN+"a")
376 self.assertEqual(realpath(ABSTFN+"a"), ABSTFN+"a/b")
377
378 os.symlink("../" + basename(dirname(ABSTFN)) + "/" +
379 basename(ABSTFN) + "c", ABSTFN+"c")
380 self.assertEqual(realpath(ABSTFN+"c"), ABSTFN+"c")
381
Brian Curtind40e6f72010-07-08 21:39:08 +0000382 # Test using relative path as well.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300383 with support.change_cwd(dirname(ABSTFN)):
384 self.assertEqual(realpath(basename(ABSTFN)), ABSTFN)
Brian Curtind40e6f72010-07-08 21:39:08 +0000385 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000386 support.unlink(ABSTFN)
387 support.unlink(ABSTFN+"1")
388 support.unlink(ABSTFN+"2")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200389 support.unlink(ABSTFN+"y")
390 support.unlink(ABSTFN+"c")
Ezio Melotti136726c2013-03-01 20:59:17 +0200391 support.unlink(ABSTFN+"a")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200392
393 @unittest.skipUnless(hasattr(os, "symlink"),
394 "Missing symlink implementation")
395 @skip_if_ABSTFN_contains_backslash
396 def test_realpath_repeated_indirect_symlinks(self):
397 # Issue #6975.
398 try:
399 os.mkdir(ABSTFN)
400 os.symlink('../' + basename(ABSTFN), ABSTFN + '/self')
401 os.symlink('self/self/self', ABSTFN + '/link')
402 self.assertEqual(realpath(ABSTFN + '/link'), ABSTFN)
403 finally:
404 support.unlink(ABSTFN + '/self')
405 support.unlink(ABSTFN + '/link')
406 safe_rmdir(ABSTFN)
407
408 @unittest.skipUnless(hasattr(os, "symlink"),
409 "Missing symlink implementation")
410 @skip_if_ABSTFN_contains_backslash
411 def test_realpath_deep_recursion(self):
412 depth = 10
Serhiy Storchakadf326912013-02-10 12:22:07 +0200413 try:
414 os.mkdir(ABSTFN)
415 for i in range(depth):
416 os.symlink('/'.join(['%d' % i] * 10), ABSTFN + '/%d' % (i + 1))
417 os.symlink('.', ABSTFN + '/0')
418 self.assertEqual(realpath(ABSTFN + '/%d' % depth), ABSTFN)
419
420 # Test using relative path as well.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300421 with support.change_cwd(ABSTFN):
422 self.assertEqual(realpath('%d' % depth), ABSTFN)
Serhiy Storchakadf326912013-02-10 12:22:07 +0200423 finally:
Serhiy Storchakadf326912013-02-10 12:22:07 +0200424 for i in range(depth + 1):
425 support.unlink(ABSTFN + '/%d' % i)
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_parents(self):
432 # We also need to resolve any symlinks in the parents of a relative
433 # path passed to realpath. E.g.: current working directory is
434 # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call
435 # realpath("a"). This should return /usr/share/doc/a/.
436 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000437 os.mkdir(ABSTFN)
438 os.mkdir(ABSTFN + "/y")
439 os.symlink(ABSTFN + "/y", ABSTFN + "/k")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000440
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300441 with support.change_cwd(ABSTFN + "/k"):
442 self.assertEqual(realpath("a"), ABSTFN + "/y/a")
Brian Curtind40e6f72010-07-08 21:39:08 +0000443 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000444 support.unlink(ABSTFN + "/k")
445 safe_rmdir(ABSTFN + "/y")
446 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000447
Brian Curtin52173d42010-12-02 18:29:18 +0000448 @unittest.skipUnless(hasattr(os, "symlink"),
449 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000450 @skip_if_ABSTFN_contains_backslash
451 def test_realpath_resolve_before_normalizing(self):
452 # Bug #990669: Symbolic links should be resolved before we
453 # normalize the path. E.g.: if we have directories 'a', 'k' and 'y'
454 # in the following hierarchy:
455 # a/k/y
456 #
457 # and a symbolic link 'link-y' pointing to 'y' in directory 'a',
458 # then realpath("link-y/..") should return 'k', not 'a'.
459 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000460 os.mkdir(ABSTFN)
461 os.mkdir(ABSTFN + "/k")
462 os.mkdir(ABSTFN + "/k/y")
463 os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000464
Brian Curtind40e6f72010-07-08 21:39:08 +0000465 # Absolute path.
466 self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k")
467 # Relative path.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300468 with support.change_cwd(dirname(ABSTFN)):
469 self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."),
470 ABSTFN + "/k")
Brian Curtind40e6f72010-07-08 21:39:08 +0000471 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000472 support.unlink(ABSTFN + "/link-y")
473 safe_rmdir(ABSTFN + "/k/y")
474 safe_rmdir(ABSTFN + "/k")
475 safe_rmdir(ABSTFN)
Tim Peters5d36a552005-06-03 22:40:27 +0000476
Brian Curtin52173d42010-12-02 18:29:18 +0000477 @unittest.skipUnless(hasattr(os, "symlink"),
478 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000479 @skip_if_ABSTFN_contains_backslash
480 def test_realpath_resolve_first(self):
481 # Bug #1213894: The first component of the path, if not absolute,
482 # must be resolved too.
Georg Brandl268e61c2005-06-03 14:28:50 +0000483
Brian Curtind40e6f72010-07-08 21:39:08 +0000484 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000485 os.mkdir(ABSTFN)
486 os.mkdir(ABSTFN + "/k")
487 os.symlink(ABSTFN, ABSTFN + "link")
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300488 with support.change_cwd(dirname(ABSTFN)):
489 base = basename(ABSTFN)
490 self.assertEqual(realpath(base + "link"), ABSTFN)
491 self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k")
Brian Curtind40e6f72010-07-08 21:39:08 +0000492 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000493 support.unlink(ABSTFN + "link")
494 safe_rmdir(ABSTFN + "/k")
495 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000496
Guido van Rossumd8faa362007-04-27 19:54:29 +0000497 def test_relpath(self):
498 (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar")
499 try:
500 curdir = os.path.split(os.getcwd())[-1]
501 self.assertRaises(ValueError, posixpath.relpath, "")
502 self.assertEqual(posixpath.relpath("a"), "a")
503 self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a")
504 self.assertEqual(posixpath.relpath("a/b"), "a/b")
505 self.assertEqual(posixpath.relpath("../a/b"), "../a/b")
506 self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000507 self.assertEqual(posixpath.relpath("a/b", "../c"),
508 "../"+curdir+"/a/b")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000509 self.assertEqual(posixpath.relpath("a", "b/c"), "../../a")
Christian Heimesfaf2f632008-01-06 16:59:19 +0000510 self.assertEqual(posixpath.relpath("a", "a"), ".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000511 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x/y/z"), '../../../foo/bar/bat')
512 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/foo/bar"), 'bat')
513 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/"), 'foo/bar/bat')
514 self.assertEqual(posixpath.relpath("/", "/foo/bar/bat"), '../../..')
515 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x"), '../foo/bar/bat')
516 self.assertEqual(posixpath.relpath("/x", "/foo/bar/bat"), '../../../x')
517 self.assertEqual(posixpath.relpath("/", "/"), '.')
518 self.assertEqual(posixpath.relpath("/a", "/a"), '.')
519 self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000520 finally:
521 os.getcwd = real_getcwd
Brett Cannonb47243a2003-06-16 21:54:50 +0000522
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000523 def test_relpath_bytes(self):
524 (real_getcwdb, os.getcwdb) = (os.getcwdb, lambda: br"/home/user/bar")
525 try:
526 curdir = os.path.split(os.getcwdb())[-1]
527 self.assertRaises(ValueError, posixpath.relpath, b"")
528 self.assertEqual(posixpath.relpath(b"a"), b"a")
529 self.assertEqual(posixpath.relpath(posixpath.abspath(b"a")), b"a")
530 self.assertEqual(posixpath.relpath(b"a/b"), b"a/b")
531 self.assertEqual(posixpath.relpath(b"../a/b"), b"../a/b")
532 self.assertEqual(posixpath.relpath(b"a", b"../b"),
533 b"../"+curdir+b"/a")
534 self.assertEqual(posixpath.relpath(b"a/b", b"../c"),
535 b"../"+curdir+b"/a/b")
536 self.assertEqual(posixpath.relpath(b"a", b"b/c"), b"../../a")
537 self.assertEqual(posixpath.relpath(b"a", b"a"), b".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000538 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x/y/z"), b'../../../foo/bar/bat')
539 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/foo/bar"), b'bat')
540 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/"), b'foo/bar/bat')
541 self.assertEqual(posixpath.relpath(b"/", b"/foo/bar/bat"), b'../../..')
542 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x"), b'../foo/bar/bat')
543 self.assertEqual(posixpath.relpath(b"/x", b"/foo/bar/bat"), b'../../../x')
544 self.assertEqual(posixpath.relpath(b"/", b"/"), b'.')
545 self.assertEqual(posixpath.relpath(b"/a", b"/a"), b'.')
546 self.assertEqual(posixpath.relpath(b"/a/b", b"/a/b"), b'.')
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000547
548 self.assertRaises(TypeError, posixpath.relpath, b"bytes", "str")
549 self.assertRaises(TypeError, posixpath.relpath, "str", b"bytes")
550 finally:
551 os.getcwdb = real_getcwdb
552
Serhiy Storchaka38220932015-03-31 15:31:53 +0300553 def test_commonpath(self):
554 def check(paths, expected):
555 self.assertEqual(posixpath.commonpath(paths), expected)
556 self.assertEqual(posixpath.commonpath([os.fsencode(p) for p in paths]),
557 os.fsencode(expected))
558 def check_error(exc, paths):
559 self.assertRaises(exc, posixpath.commonpath, paths)
560 self.assertRaises(exc, posixpath.commonpath,
561 [os.fsencode(p) for p in paths])
562
563 self.assertRaises(ValueError, posixpath.commonpath, [])
564 check_error(ValueError, ['/usr', 'usr'])
565 check_error(ValueError, ['usr', '/usr'])
566
567 check(['/usr/local'], '/usr/local')
568 check(['/usr/local', '/usr/local'], '/usr/local')
569 check(['/usr/local/', '/usr/local'], '/usr/local')
570 check(['/usr/local/', '/usr/local/'], '/usr/local')
571 check(['/usr//local', '//usr/local'], '/usr/local')
572 check(['/usr/./local', '/./usr/local'], '/usr/local')
573 check(['/', '/dev'], '/')
574 check(['/usr', '/dev'], '/')
575 check(['/usr/lib/', '/usr/lib/python3'], '/usr/lib')
576 check(['/usr/lib/', '/usr/lib64/'], '/usr')
577
578 check(['/usr/lib', '/usr/lib64'], '/usr')
579 check(['/usr/lib/', '/usr/lib64'], '/usr')
580
581 check(['spam'], 'spam')
582 check(['spam', 'spam'], 'spam')
583 check(['spam', 'alot'], '')
584 check(['and/jam', 'and/spam'], 'and')
585 check(['and//jam', 'and/spam//'], 'and')
586 check(['and/./jam', './and/spam'], 'and')
587 check(['and/jam', 'and/spam', 'alot'], '')
588 check(['and/jam', 'and/spam', 'and'], 'and')
589
590 check([''], '')
591 check(['', 'spam/alot'], '')
592 check_error(ValueError, ['', '/spam/alot'])
593
594 self.assertRaises(TypeError, posixpath.commonpath,
595 [b'/usr/lib/', '/usr/lib/python3'])
596 self.assertRaises(TypeError, posixpath.commonpath,
597 [b'/usr/lib/', 'usr/lib/python3'])
598 self.assertRaises(TypeError, posixpath.commonpath,
599 [b'usr/lib/', '/usr/lib/python3'])
600 self.assertRaises(TypeError, posixpath.commonpath,
601 ['/usr/lib/', b'/usr/lib/python3'])
602 self.assertRaises(TypeError, posixpath.commonpath,
603 ['/usr/lib/', b'usr/lib/python3'])
604 self.assertRaises(TypeError, posixpath.commonpath,
605 ['usr/lib/', b'/usr/lib/python3'])
606
Florent Xiclunac9c79782010-03-08 12:24:53 +0000607
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200608class PosixCommonTest(test_genericpath.CommonTest, unittest.TestCase):
Florent Xiclunac9c79782010-03-08 12:24:53 +0000609 pathmodule = posixpath
610 attributes = ['relpath', 'samefile', 'sameopenfile', 'samestat']
611
612
Brett Cannon3f9183b2016-08-26 14:44:48 -0700613class PathLikeTests(unittest.TestCase):
614
615 path = posixpath
616
Brett Cannon3f9183b2016-08-26 14:44:48 -0700617 def setUp(self):
618 self.file_name = support.TESTFN.lower()
Miss Islington (bot)a13b6542018-03-02 02:17:51 -0800619 self.file_path = FakePath(support.TESTFN)
Brett Cannon3f9183b2016-08-26 14:44:48 -0700620 self.addCleanup(support.unlink, self.file_name)
621 with open(self.file_name, 'xb', 0) as file:
622 file.write(b"test_posixpath.PathLikeTests")
623
624 def assertPathEqual(self, func):
625 self.assertEqual(func(self.file_path), func(self.file_name))
626
627 def test_path_normcase(self):
628 self.assertPathEqual(self.path.normcase)
629
630 def test_path_isabs(self):
631 self.assertPathEqual(self.path.isabs)
632
633 def test_path_join(self):
Miss Islington (bot)a13b6542018-03-02 02:17:51 -0800634 self.assertEqual(self.path.join('a', FakePath('b'), 'c'),
Brett Cannon3f9183b2016-08-26 14:44:48 -0700635 self.path.join('a', 'b', 'c'))
636
637 def test_path_split(self):
638 self.assertPathEqual(self.path.split)
639
640 def test_path_splitext(self):
641 self.assertPathEqual(self.path.splitext)
642
643 def test_path_splitdrive(self):
644 self.assertPathEqual(self.path.splitdrive)
645
646 def test_path_basename(self):
647 self.assertPathEqual(self.path.basename)
648
649 def test_path_dirname(self):
650 self.assertPathEqual(self.path.dirname)
651
652 def test_path_islink(self):
653 self.assertPathEqual(self.path.islink)
654
655 def test_path_lexists(self):
656 self.assertPathEqual(self.path.lexists)
657
658 def test_path_ismount(self):
659 self.assertPathEqual(self.path.ismount)
660
661 def test_path_expanduser(self):
662 self.assertPathEqual(self.path.expanduser)
663
664 def test_path_expandvars(self):
665 self.assertPathEqual(self.path.expandvars)
666
667 def test_path_normpath(self):
668 self.assertPathEqual(self.path.normpath)
669
670 def test_path_abspath(self):
671 self.assertPathEqual(self.path.abspath)
672
673 def test_path_realpath(self):
674 self.assertPathEqual(self.path.realpath)
675
676 def test_path_relpath(self):
677 self.assertPathEqual(self.path.relpath)
678
679 def test_path_commonpath(self):
680 common_path = self.path.commonpath([self.file_path, self.file_name])
681 self.assertEqual(common_path, self.file_name)
682
683
Brett Cannonb47243a2003-06-16 21:54:50 +0000684if __name__=="__main__":
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200685 unittest.main()