blob: 983e2dd6ff2763fd374238b36d1c5ad3773f5ce6 [file] [log] [blame]
Brian Curtind40e6f72010-07-08 21:39:08 +00001import os
Victor Stinner1ab6c2d2011-11-15 22:27:41 +01002import posixpath
Victor Stinner1ab6c2d2011-11-15 22:27:41 +01003import unittest
4import warnings
Georg Brandl89fad142010-03-14 10:23:39 +00005from posixpath import realpath, abspath, dirname, basename
Victor Stinner1ab6c2d2011-11-15 22:27:41 +01006from test import support, test_genericpath
Serhiy Storchakab21d1552018-03-02 11:53:51 +02007from test.support import FakePath
Victor Stinnerf2f45552018-12-05 16:49:35 +01008from 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)
Serhiy Storchaka0185f342018-09-18 11:28:51 +0300157
Serhiy Storchaka17a00882018-06-16 13:25:55 +0300158 with open(support.TESTFN + "1", "wb") as f:
Guido van Rossum7dcb8442007-08-27 23:26:56 +0000159 f.write(b"foo")
Serhiy Storchaka17a00882018-06-16 13:25:55 +0300160 self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
Serhiy Storchaka0185f342018-09-18 11:28:51 +0300161
Serhiy Storchaka17a00882018-06-16 13:25:55 +0300162 if support.can_symlink():
163 os.symlink(support.TESTFN + "1", support.TESTFN + "2")
164 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
165 os.remove(support.TESTFN + "1")
166 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
167 self.assertIs(posixpath.exists(support.TESTFN + "2"), False)
168 self.assertIs(posixpath.lexists(support.TESTFN + "2"), True)
Brett Cannonb47243a2003-06-16 21:54:50 +0000169
Serhiy Storchaka0185f342018-09-18 11:28:51 +0300170 self.assertIs(posixpath.islink(support.TESTFN + "\udfff"), False)
171 self.assertIs(posixpath.islink(os.fsencode(support.TESTFN) + b"\xff"), False)
172 self.assertIs(posixpath.islink(support.TESTFN + "\x00"), False)
173 self.assertIs(posixpath.islink(os.fsencode(support.TESTFN) + b"\x00"), False)
174
Brett Cannonb47243a2003-06-16 21:54:50 +0000175 def test_ismount(self):
176 self.assertIs(posixpath.ismount("/"), True)
Serhiy Storchaka17a00882018-06-16 13:25:55 +0300177 self.assertIs(posixpath.ismount(b"/"), True)
Michael Foord07926f02011-03-16 17:19:16 -0400178
179 def test_ismount_non_existent(self):
180 # Non-existent mountpoint.
181 self.assertIs(posixpath.ismount(ABSTFN), False)
182 try:
183 os.mkdir(ABSTFN)
184 self.assertIs(posixpath.ismount(ABSTFN), False)
185 finally:
186 safe_rmdir(ABSTFN)
187
Serhiy Storchaka0185f342018-09-18 11:28:51 +0300188 self.assertIs(posixpath.ismount('/\udfff'), False)
189 self.assertIs(posixpath.ismount(b'/\xff'), False)
190 self.assertIs(posixpath.ismount('/\x00'), False)
191 self.assertIs(posixpath.ismount(b'/\x00'), False)
192
Michael Foord07926f02011-03-16 17:19:16 -0400193 @unittest.skipUnless(support.can_symlink(),
194 "Test requires symlink support")
195 def test_ismount_symlinks(self):
196 # Symlinks are never mountpoints.
197 try:
198 os.symlink("/", ABSTFN)
199 self.assertIs(posixpath.ismount(ABSTFN), False)
200 finally:
201 os.unlink(ABSTFN)
202
203 @unittest.skipIf(posix is None, "Test requires posix module")
204 def test_ismount_different_device(self):
205 # Simulate the path being on a different device from its parent by
206 # mocking out st_dev.
207 save_lstat = os.lstat
208 def fake_lstat(path):
209 st_ino = 0
210 st_dev = 0
211 if path == ABSTFN:
212 st_dev = 1
213 st_ino = 1
214 return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
215 try:
216 os.lstat = fake_lstat
217 self.assertIs(posixpath.ismount(ABSTFN), True)
218 finally:
219 os.lstat = save_lstat
Brett Cannonb47243a2003-06-16 21:54:50 +0000220
R David Murray750018b2016-08-18 21:27:48 -0400221 @unittest.skipIf(posix is None, "Test requires posix module")
222 def test_ismount_directory_not_readable(self):
223 # issue #2466: Simulate ismount run on a directory that is not
224 # readable, which used to return False.
225 save_lstat = os.lstat
226 def fake_lstat(path):
227 st_ino = 0
228 st_dev = 0
229 if path.startswith(ABSTFN) and path != ABSTFN:
230 # ismount tries to read something inside the ABSTFN directory;
231 # simulate this being forbidden (no read permission).
232 raise OSError("Fake [Errno 13] Permission denied")
233 if path == ABSTFN:
234 st_dev = 1
235 st_ino = 1
236 return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
237 try:
238 os.lstat = fake_lstat
239 self.assertIs(posixpath.ismount(ABSTFN), True)
240 finally:
241 os.lstat = save_lstat
242
Brett Cannonb47243a2003-06-16 21:54:50 +0000243 def test_expanduser(self):
244 self.assertEqual(posixpath.expanduser("foo"), "foo")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000245 self.assertEqual(posixpath.expanduser(b"foo"), b"foo")
Victor Stinnerf2f45552018-12-05 16:49:35 +0100246
247 def test_expanduser_home_envvar(self):
Serhiy Storchakaa3fd0b22016-05-03 21:17:03 +0300248 with support.EnvironmentVarGuard() as env:
Victor Stinnerf2f45552018-12-05 16:49:35 +0100249 env['HOME'] = '/home/victor'
250 self.assertEqual(posixpath.expanduser("~"), "/home/victor")
251
252 # expanduser() strips trailing slash
253 env['HOME'] = '/home/victor/'
254 self.assertEqual(posixpath.expanduser("~"), "/home/victor")
255
Serhiy Storchakaa3fd0b22016-05-03 21:17:03 +0300256 for home in '/', '', '//', '///':
257 with self.subTest(home=home):
258 env['HOME'] = home
259 self.assertEqual(posixpath.expanduser("~"), "/")
260 self.assertEqual(posixpath.expanduser("~/"), "/")
261 self.assertEqual(posixpath.expanduser("~/foo"), "/foo")
Brett Cannonb47243a2003-06-16 21:54:50 +0000262
Victor Stinnerf2f45552018-12-05 16:49:35 +0100263 def test_expanduser_pwd(self):
264 pwd = support.import_module('pwd')
265
266 self.assertIsInstance(posixpath.expanduser("~/"), str)
267 self.assertIsInstance(posixpath.expanduser(b"~/"), bytes)
268
269 # if home directory == root directory, this test makes no sense
270 if posixpath.expanduser("~") != '/':
271 self.assertEqual(
272 posixpath.expanduser("~") + "/",
273 posixpath.expanduser("~/")
274 )
275 self.assertEqual(
276 posixpath.expanduser(b"~") + b"/",
277 posixpath.expanduser(b"~/")
278 )
279 self.assertIsInstance(posixpath.expanduser("~root/"), str)
280 self.assertIsInstance(posixpath.expanduser("~foo/"), str)
281 self.assertIsInstance(posixpath.expanduser(b"~root/"), bytes)
282 self.assertIsInstance(posixpath.expanduser(b"~foo/"), bytes)
283
284 with support.EnvironmentVarGuard() as env:
285 # expanduser should fall back to using the password database
286 del env['HOME']
287
288 home = pwd.getpwuid(os.getuid()).pw_dir
289 # $HOME can end with a trailing /, so strip it (see #17809)
290 home = home.rstrip("/") or '/'
291 self.assertEqual(posixpath.expanduser("~"), home)
292
293 # bpo-10496: If the HOME environment variable is not set and the
294 # user (current identifier or name in the path) doesn't exist in
295 # the password database (pwd.getuid() or pwd.getpwnam() fail),
296 # expanduser() must return the path unchanged.
297 with mock.patch.object(pwd, 'getpwuid', side_effect=KeyError), \
298 mock.patch.object(pwd, 'getpwnam', side_effect=KeyError):
299 for path in ('~', '~/.local', '~vstinner/'):
300 self.assertEqual(posixpath.expanduser(path), path)
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000301
Brett Cannonb47243a2003-06-16 21:54:50 +0000302 def test_normpath(self):
303 self.assertEqual(posixpath.normpath(""), ".")
304 self.assertEqual(posixpath.normpath("/"), "/")
305 self.assertEqual(posixpath.normpath("//"), "//")
306 self.assertEqual(posixpath.normpath("///"), "/")
307 self.assertEqual(posixpath.normpath("///foo/.//bar//"), "/foo/bar")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000308 self.assertEqual(posixpath.normpath("///foo/.//bar//.//..//.//baz"),
309 "/foo/baz")
Brett Cannonb47243a2003-06-16 21:54:50 +0000310 self.assertEqual(posixpath.normpath("///..//./foo/.//bar"), "/foo/bar")
311
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000312 self.assertEqual(posixpath.normpath(b""), b".")
313 self.assertEqual(posixpath.normpath(b"/"), b"/")
314 self.assertEqual(posixpath.normpath(b"//"), b"//")
315 self.assertEqual(posixpath.normpath(b"///"), b"/")
316 self.assertEqual(posixpath.normpath(b"///foo/.//bar//"), b"/foo/bar")
317 self.assertEqual(posixpath.normpath(b"///foo/.//bar//.//..//.//baz"),
318 b"/foo/baz")
319 self.assertEqual(posixpath.normpath(b"///..//./foo/.//bar"),
320 b"/foo/bar")
321
Serhiy Storchaka1548ed62013-02-18 13:32:30 +0200322 @skip_if_ABSTFN_contains_backslash
Serhiy Storchaka467393d2013-02-18 12:21:04 +0200323 def test_realpath_curdir(self):
324 self.assertEqual(realpath('.'), os.getcwd())
325 self.assertEqual(realpath('./.'), os.getcwd())
326 self.assertEqual(realpath('/'.join(['.'] * 100)), os.getcwd())
327
328 self.assertEqual(realpath(b'.'), os.getcwdb())
329 self.assertEqual(realpath(b'./.'), os.getcwdb())
330 self.assertEqual(realpath(b'/'.join([b'.'] * 100)), os.getcwdb())
331
Serhiy Storchaka1548ed62013-02-18 13:32:30 +0200332 @skip_if_ABSTFN_contains_backslash
Serhiy Storchaka467393d2013-02-18 12:21:04 +0200333 def test_realpath_pardir(self):
334 self.assertEqual(realpath('..'), dirname(os.getcwd()))
335 self.assertEqual(realpath('../..'), dirname(dirname(os.getcwd())))
336 self.assertEqual(realpath('/'.join(['..'] * 100)), '/')
337
338 self.assertEqual(realpath(b'..'), dirname(os.getcwdb()))
339 self.assertEqual(realpath(b'../..'), dirname(dirname(os.getcwdb())))
340 self.assertEqual(realpath(b'/'.join([b'..'] * 100)), b'/')
341
Brian Curtin52173d42010-12-02 18:29:18 +0000342 @unittest.skipUnless(hasattr(os, "symlink"),
343 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000344 @skip_if_ABSTFN_contains_backslash
345 def test_realpath_basic(self):
346 # Basic operation.
347 try:
348 os.symlink(ABSTFN+"1", ABSTFN)
349 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
350 finally:
351 support.unlink(ABSTFN)
Tim Petersa45cacf2004-08-20 03:47:14 +0000352
Brian Curtin52173d42010-12-02 18:29:18 +0000353 @unittest.skipUnless(hasattr(os, "symlink"),
354 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000355 @skip_if_ABSTFN_contains_backslash
Michael Foord07926f02011-03-16 17:19:16 -0400356 def test_realpath_relative(self):
357 try:
358 os.symlink(posixpath.relpath(ABSTFN+"1"), ABSTFN)
359 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
360 finally:
361 support.unlink(ABSTFN)
362
363 @unittest.skipUnless(hasattr(os, "symlink"),
364 "Missing symlink implementation")
365 @skip_if_ABSTFN_contains_backslash
Brian Curtind40e6f72010-07-08 21:39:08 +0000366 def test_realpath_symlink_loops(self):
367 # Bug #930024, return the path unchanged if we get into an infinite
368 # symlink loop.
369 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000370 os.symlink(ABSTFN, ABSTFN)
371 self.assertEqual(realpath(ABSTFN), ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000372
Brian Curtind40e6f72010-07-08 21:39:08 +0000373 os.symlink(ABSTFN+"1", ABSTFN+"2")
374 os.symlink(ABSTFN+"2", ABSTFN+"1")
375 self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1")
376 self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000377
Serhiy Storchakadf326912013-02-10 12:22:07 +0200378 self.assertEqual(realpath(ABSTFN+"1/x"), ABSTFN+"1/x")
379 self.assertEqual(realpath(ABSTFN+"1/.."), dirname(ABSTFN))
380 self.assertEqual(realpath(ABSTFN+"1/../x"), dirname(ABSTFN) + "/x")
381 os.symlink(ABSTFN+"x", ABSTFN+"y")
382 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "y"),
383 ABSTFN + "y")
384 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "1"),
385 ABSTFN + "1")
386
387 os.symlink(basename(ABSTFN) + "a/b", ABSTFN+"a")
388 self.assertEqual(realpath(ABSTFN+"a"), ABSTFN+"a/b")
389
390 os.symlink("../" + basename(dirname(ABSTFN)) + "/" +
391 basename(ABSTFN) + "c", ABSTFN+"c")
392 self.assertEqual(realpath(ABSTFN+"c"), ABSTFN+"c")
393
Brian Curtind40e6f72010-07-08 21:39:08 +0000394 # Test using relative path as well.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300395 with support.change_cwd(dirname(ABSTFN)):
396 self.assertEqual(realpath(basename(ABSTFN)), ABSTFN)
Brian Curtind40e6f72010-07-08 21:39:08 +0000397 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000398 support.unlink(ABSTFN)
399 support.unlink(ABSTFN+"1")
400 support.unlink(ABSTFN+"2")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200401 support.unlink(ABSTFN+"y")
402 support.unlink(ABSTFN+"c")
Ezio Melotti136726c2013-03-01 20:59:17 +0200403 support.unlink(ABSTFN+"a")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200404
405 @unittest.skipUnless(hasattr(os, "symlink"),
406 "Missing symlink implementation")
407 @skip_if_ABSTFN_contains_backslash
408 def test_realpath_repeated_indirect_symlinks(self):
409 # Issue #6975.
410 try:
411 os.mkdir(ABSTFN)
412 os.symlink('../' + basename(ABSTFN), ABSTFN + '/self')
413 os.symlink('self/self/self', ABSTFN + '/link')
414 self.assertEqual(realpath(ABSTFN + '/link'), ABSTFN)
415 finally:
416 support.unlink(ABSTFN + '/self')
417 support.unlink(ABSTFN + '/link')
418 safe_rmdir(ABSTFN)
419
420 @unittest.skipUnless(hasattr(os, "symlink"),
421 "Missing symlink implementation")
422 @skip_if_ABSTFN_contains_backslash
423 def test_realpath_deep_recursion(self):
424 depth = 10
Serhiy Storchakadf326912013-02-10 12:22:07 +0200425 try:
426 os.mkdir(ABSTFN)
427 for i in range(depth):
428 os.symlink('/'.join(['%d' % i] * 10), ABSTFN + '/%d' % (i + 1))
429 os.symlink('.', ABSTFN + '/0')
430 self.assertEqual(realpath(ABSTFN + '/%d' % depth), ABSTFN)
431
432 # Test using relative path as well.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300433 with support.change_cwd(ABSTFN):
434 self.assertEqual(realpath('%d' % depth), ABSTFN)
Serhiy Storchakadf326912013-02-10 12:22:07 +0200435 finally:
Serhiy Storchakadf326912013-02-10 12:22:07 +0200436 for i in range(depth + 1):
437 support.unlink(ABSTFN + '/%d' % i)
438 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000439
Brian Curtin52173d42010-12-02 18:29:18 +0000440 @unittest.skipUnless(hasattr(os, "symlink"),
441 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000442 @skip_if_ABSTFN_contains_backslash
443 def test_realpath_resolve_parents(self):
444 # We also need to resolve any symlinks in the parents of a relative
445 # path passed to realpath. E.g.: current working directory is
446 # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call
447 # realpath("a"). This should return /usr/share/doc/a/.
448 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000449 os.mkdir(ABSTFN)
450 os.mkdir(ABSTFN + "/y")
451 os.symlink(ABSTFN + "/y", ABSTFN + "/k")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000452
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300453 with support.change_cwd(ABSTFN + "/k"):
454 self.assertEqual(realpath("a"), ABSTFN + "/y/a")
Brian Curtind40e6f72010-07-08 21:39:08 +0000455 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000456 support.unlink(ABSTFN + "/k")
457 safe_rmdir(ABSTFN + "/y")
458 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000459
Brian Curtin52173d42010-12-02 18:29:18 +0000460 @unittest.skipUnless(hasattr(os, "symlink"),
461 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000462 @skip_if_ABSTFN_contains_backslash
463 def test_realpath_resolve_before_normalizing(self):
464 # Bug #990669: Symbolic links should be resolved before we
465 # normalize the path. E.g.: if we have directories 'a', 'k' and 'y'
466 # in the following hierarchy:
467 # a/k/y
468 #
469 # and a symbolic link 'link-y' pointing to 'y' in directory 'a',
470 # then realpath("link-y/..") should return 'k', not 'a'.
471 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000472 os.mkdir(ABSTFN)
473 os.mkdir(ABSTFN + "/k")
474 os.mkdir(ABSTFN + "/k/y")
475 os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000476
Brian Curtind40e6f72010-07-08 21:39:08 +0000477 # Absolute path.
478 self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k")
479 # Relative path.
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300480 with support.change_cwd(dirname(ABSTFN)):
481 self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."),
482 ABSTFN + "/k")
Brian Curtind40e6f72010-07-08 21:39:08 +0000483 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000484 support.unlink(ABSTFN + "/link-y")
485 safe_rmdir(ABSTFN + "/k/y")
486 safe_rmdir(ABSTFN + "/k")
487 safe_rmdir(ABSTFN)
Tim Peters5d36a552005-06-03 22:40:27 +0000488
Brian Curtin52173d42010-12-02 18:29:18 +0000489 @unittest.skipUnless(hasattr(os, "symlink"),
490 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000491 @skip_if_ABSTFN_contains_backslash
492 def test_realpath_resolve_first(self):
493 # Bug #1213894: The first component of the path, if not absolute,
494 # must be resolved too.
Georg Brandl268e61c2005-06-03 14:28:50 +0000495
Brian Curtind40e6f72010-07-08 21:39:08 +0000496 try:
Brian Curtind40e6f72010-07-08 21:39:08 +0000497 os.mkdir(ABSTFN)
498 os.mkdir(ABSTFN + "/k")
499 os.symlink(ABSTFN, ABSTFN + "link")
Serhiy Storchaka2a23adf2015-09-06 14:13:25 +0300500 with support.change_cwd(dirname(ABSTFN)):
501 base = basename(ABSTFN)
502 self.assertEqual(realpath(base + "link"), ABSTFN)
503 self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k")
Brian Curtind40e6f72010-07-08 21:39:08 +0000504 finally:
Brian Curtind40e6f72010-07-08 21:39:08 +0000505 support.unlink(ABSTFN + "link")
506 safe_rmdir(ABSTFN + "/k")
507 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000508
Guido van Rossumd8faa362007-04-27 19:54:29 +0000509 def test_relpath(self):
510 (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar")
511 try:
512 curdir = os.path.split(os.getcwd())[-1]
513 self.assertRaises(ValueError, posixpath.relpath, "")
514 self.assertEqual(posixpath.relpath("a"), "a")
515 self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a")
516 self.assertEqual(posixpath.relpath("a/b"), "a/b")
517 self.assertEqual(posixpath.relpath("../a/b"), "../a/b")
518 self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000519 self.assertEqual(posixpath.relpath("a/b", "../c"),
520 "../"+curdir+"/a/b")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000521 self.assertEqual(posixpath.relpath("a", "b/c"), "../../a")
Christian Heimesfaf2f632008-01-06 16:59:19 +0000522 self.assertEqual(posixpath.relpath("a", "a"), ".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000523 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x/y/z"), '../../../foo/bar/bat')
524 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/foo/bar"), 'bat')
525 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/"), 'foo/bar/bat')
526 self.assertEqual(posixpath.relpath("/", "/foo/bar/bat"), '../../..')
527 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x"), '../foo/bar/bat')
528 self.assertEqual(posixpath.relpath("/x", "/foo/bar/bat"), '../../../x')
529 self.assertEqual(posixpath.relpath("/", "/"), '.')
530 self.assertEqual(posixpath.relpath("/a", "/a"), '.')
531 self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000532 finally:
533 os.getcwd = real_getcwd
Brett Cannonb47243a2003-06-16 21:54:50 +0000534
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000535 def test_relpath_bytes(self):
536 (real_getcwdb, os.getcwdb) = (os.getcwdb, lambda: br"/home/user/bar")
537 try:
538 curdir = os.path.split(os.getcwdb())[-1]
539 self.assertRaises(ValueError, posixpath.relpath, b"")
540 self.assertEqual(posixpath.relpath(b"a"), b"a")
541 self.assertEqual(posixpath.relpath(posixpath.abspath(b"a")), b"a")
542 self.assertEqual(posixpath.relpath(b"a/b"), b"a/b")
543 self.assertEqual(posixpath.relpath(b"../a/b"), b"../a/b")
544 self.assertEqual(posixpath.relpath(b"a", b"../b"),
545 b"../"+curdir+b"/a")
546 self.assertEqual(posixpath.relpath(b"a/b", b"../c"),
547 b"../"+curdir+b"/a/b")
548 self.assertEqual(posixpath.relpath(b"a", b"b/c"), b"../../a")
549 self.assertEqual(posixpath.relpath(b"a", b"a"), b".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000550 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x/y/z"), b'../../../foo/bar/bat')
551 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/foo/bar"), b'bat')
552 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/"), b'foo/bar/bat')
553 self.assertEqual(posixpath.relpath(b"/", b"/foo/bar/bat"), b'../../..')
554 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x"), b'../foo/bar/bat')
555 self.assertEqual(posixpath.relpath(b"/x", b"/foo/bar/bat"), b'../../../x')
556 self.assertEqual(posixpath.relpath(b"/", b"/"), b'.')
557 self.assertEqual(posixpath.relpath(b"/a", b"/a"), b'.')
558 self.assertEqual(posixpath.relpath(b"/a/b", b"/a/b"), b'.')
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000559
560 self.assertRaises(TypeError, posixpath.relpath, b"bytes", "str")
561 self.assertRaises(TypeError, posixpath.relpath, "str", b"bytes")
562 finally:
563 os.getcwdb = real_getcwdb
564
Serhiy Storchaka38220932015-03-31 15:31:53 +0300565 def test_commonpath(self):
566 def check(paths, expected):
567 self.assertEqual(posixpath.commonpath(paths), expected)
568 self.assertEqual(posixpath.commonpath([os.fsencode(p) for p in paths]),
569 os.fsencode(expected))
570 def check_error(exc, paths):
571 self.assertRaises(exc, posixpath.commonpath, paths)
572 self.assertRaises(exc, posixpath.commonpath,
573 [os.fsencode(p) for p in paths])
574
575 self.assertRaises(ValueError, posixpath.commonpath, [])
576 check_error(ValueError, ['/usr', 'usr'])
577 check_error(ValueError, ['usr', '/usr'])
578
579 check(['/usr/local'], '/usr/local')
580 check(['/usr/local', '/usr/local'], '/usr/local')
581 check(['/usr/local/', '/usr/local'], '/usr/local')
582 check(['/usr/local/', '/usr/local/'], '/usr/local')
583 check(['/usr//local', '//usr/local'], '/usr/local')
584 check(['/usr/./local', '/./usr/local'], '/usr/local')
585 check(['/', '/dev'], '/')
586 check(['/usr', '/dev'], '/')
587 check(['/usr/lib/', '/usr/lib/python3'], '/usr/lib')
588 check(['/usr/lib/', '/usr/lib64/'], '/usr')
589
590 check(['/usr/lib', '/usr/lib64'], '/usr')
591 check(['/usr/lib/', '/usr/lib64'], '/usr')
592
593 check(['spam'], 'spam')
594 check(['spam', 'spam'], 'spam')
595 check(['spam', 'alot'], '')
596 check(['and/jam', 'and/spam'], 'and')
597 check(['and//jam', 'and/spam//'], 'and')
598 check(['and/./jam', './and/spam'], 'and')
599 check(['and/jam', 'and/spam', 'alot'], '')
600 check(['and/jam', 'and/spam', 'and'], 'and')
601
602 check([''], '')
603 check(['', 'spam/alot'], '')
604 check_error(ValueError, ['', '/spam/alot'])
605
606 self.assertRaises(TypeError, posixpath.commonpath,
607 [b'/usr/lib/', '/usr/lib/python3'])
608 self.assertRaises(TypeError, posixpath.commonpath,
609 [b'/usr/lib/', 'usr/lib/python3'])
610 self.assertRaises(TypeError, posixpath.commonpath,
611 [b'usr/lib/', '/usr/lib/python3'])
612 self.assertRaises(TypeError, posixpath.commonpath,
613 ['/usr/lib/', b'/usr/lib/python3'])
614 self.assertRaises(TypeError, posixpath.commonpath,
615 ['/usr/lib/', b'usr/lib/python3'])
616 self.assertRaises(TypeError, posixpath.commonpath,
617 ['usr/lib/', b'/usr/lib/python3'])
618
Florent Xiclunac9c79782010-03-08 12:24:53 +0000619
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200620class PosixCommonTest(test_genericpath.CommonTest, unittest.TestCase):
Florent Xiclunac9c79782010-03-08 12:24:53 +0000621 pathmodule = posixpath
622 attributes = ['relpath', 'samefile', 'sameopenfile', 'samestat']
623
624
Brett Cannon3f9183b2016-08-26 14:44:48 -0700625class PathLikeTests(unittest.TestCase):
626
627 path = posixpath
628
Brett Cannon3f9183b2016-08-26 14:44:48 -0700629 def setUp(self):
630 self.file_name = support.TESTFN.lower()
Serhiy Storchakab21d1552018-03-02 11:53:51 +0200631 self.file_path = FakePath(support.TESTFN)
Brett Cannon3f9183b2016-08-26 14:44:48 -0700632 self.addCleanup(support.unlink, self.file_name)
633 with open(self.file_name, 'xb', 0) as file:
634 file.write(b"test_posixpath.PathLikeTests")
635
636 def assertPathEqual(self, func):
637 self.assertEqual(func(self.file_path), func(self.file_name))
638
639 def test_path_normcase(self):
640 self.assertPathEqual(self.path.normcase)
641
642 def test_path_isabs(self):
643 self.assertPathEqual(self.path.isabs)
644
645 def test_path_join(self):
Serhiy Storchakab21d1552018-03-02 11:53:51 +0200646 self.assertEqual(self.path.join('a', FakePath('b'), 'c'),
Brett Cannon3f9183b2016-08-26 14:44:48 -0700647 self.path.join('a', 'b', 'c'))
648
649 def test_path_split(self):
650 self.assertPathEqual(self.path.split)
651
652 def test_path_splitext(self):
653 self.assertPathEqual(self.path.splitext)
654
655 def test_path_splitdrive(self):
656 self.assertPathEqual(self.path.splitdrive)
657
658 def test_path_basename(self):
659 self.assertPathEqual(self.path.basename)
660
661 def test_path_dirname(self):
662 self.assertPathEqual(self.path.dirname)
663
664 def test_path_islink(self):
665 self.assertPathEqual(self.path.islink)
666
667 def test_path_lexists(self):
668 self.assertPathEqual(self.path.lexists)
669
670 def test_path_ismount(self):
671 self.assertPathEqual(self.path.ismount)
672
673 def test_path_expanduser(self):
674 self.assertPathEqual(self.path.expanduser)
675
676 def test_path_expandvars(self):
677 self.assertPathEqual(self.path.expandvars)
678
679 def test_path_normpath(self):
680 self.assertPathEqual(self.path.normpath)
681
682 def test_path_abspath(self):
683 self.assertPathEqual(self.path.abspath)
684
685 def test_path_realpath(self):
686 self.assertPathEqual(self.path.realpath)
687
688 def test_path_relpath(self):
689 self.assertPathEqual(self.path.relpath)
690
691 def test_path_commonpath(self):
692 common_path = self.path.commonpath([self.file_path, self.file_name])
693 self.assertEqual(common_path, self.file_name)
694
695
Brett Cannonb47243a2003-06-16 21:54:50 +0000696if __name__=="__main__":
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200697 unittest.main()