blob: 5d0f5b74e2ed4c5f42c5861f806759cbc395cd1f [file] [log] [blame]
Brett Cannonb47243a2003-06-16 21:54:50 +00001import unittest
Florent Xiclunac9c79782010-03-08 12:24:53 +00002from test import support, test_genericpath
Skip Montanaroe809b002000-07-12 00:20:08 +00003
Hynek Schlawackc5a45662012-07-17 13:05:43 +02004import itertools
Brian Curtind40e6f72010-07-08 21:39:08 +00005import posixpath
6import os
7import sys
Georg Brandl89fad142010-03-14 10:23:39 +00008from posixpath import realpath, abspath, dirname, basename
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
Hynek Schlawackc5a45662012-07-17 13:05:43 +020060 def check_error_msg(list_of_args, msg):
61 """Check posixpath.join raises friendly TypeErrors."""
62 for args in (item for perm in list_of_args
63 for item in itertools.permutations(perm)):
Hynek Schlawack7cdc2bd2012-07-17 10:48:19 +020064 with self.assertRaises(TypeError) as cm:
65 posixpath.join(*args)
Hynek Schlawackc5a45662012-07-17 13:05:43 +020066 self.assertEqual(msg, cm.exception.args[0])
Hynek Schlawack7cdc2bd2012-07-17 10:48:19 +020067
Hynek Schlawackc5a45662012-07-17 13:05:43 +020068 check_error_msg([[b'bytes', 'str'], [bytearray(b'bytes'), 'str']],
69 "Can't mix strings and bytes in path components.")
70 # regression, see #15377
71 with self.assertRaises(TypeError) as cm:
Hynek Schlawack0b350c62012-07-17 14:28:44 +020072 posixpath.join(None, 'str')
Hynek Schlawackc5a45662012-07-17 13:05:43 +020073 self.assertNotEqual("Can't mix strings and bytes in path components.",
74 cm.exception.args[0])
Skip Montanaroe809b002000-07-12 00:20:08 +000075
Brett Cannonb47243a2003-06-16 21:54:50 +000076 def test_split(self):
77 self.assertEqual(posixpath.split("/foo/bar"), ("/foo", "bar"))
78 self.assertEqual(posixpath.split("/"), ("/", ""))
79 self.assertEqual(posixpath.split("foo"), ("", "foo"))
80 self.assertEqual(posixpath.split("////foo"), ("////", "foo"))
81 self.assertEqual(posixpath.split("//foo//bar"), ("//foo", "bar"))
82
Guido van Rossumf0af3e32008-10-02 18:55:37 +000083 self.assertEqual(posixpath.split(b"/foo/bar"), (b"/foo", b"bar"))
84 self.assertEqual(posixpath.split(b"/"), (b"/", b""))
85 self.assertEqual(posixpath.split(b"foo"), (b"", b"foo"))
86 self.assertEqual(posixpath.split(b"////foo"), (b"////", b"foo"))
87 self.assertEqual(posixpath.split(b"//foo//bar"), (b"//foo", b"bar"))
88
Guido van Rossumd8faa362007-04-27 19:54:29 +000089 def splitextTest(self, path, filename, ext):
90 self.assertEqual(posixpath.splitext(path), (filename, ext))
91 self.assertEqual(posixpath.splitext("/" + path), ("/" + filename, ext))
Guido van Rossumf0af3e32008-10-02 18:55:37 +000092 self.assertEqual(posixpath.splitext("abc/" + path),
93 ("abc/" + filename, ext))
94 self.assertEqual(posixpath.splitext("abc.def/" + path),
95 ("abc.def/" + filename, ext))
96 self.assertEqual(posixpath.splitext("/abc.def/" + path),
97 ("/abc.def/" + filename, ext))
98 self.assertEqual(posixpath.splitext(path + "/"),
99 (filename + ext + "/", ""))
100
101 path = bytes(path, "ASCII")
102 filename = bytes(filename, "ASCII")
103 ext = bytes(ext, "ASCII")
104
105 self.assertEqual(posixpath.splitext(path), (filename, ext))
106 self.assertEqual(posixpath.splitext(b"/" + path),
107 (b"/" + filename, ext))
108 self.assertEqual(posixpath.splitext(b"abc/" + path),
109 (b"abc/" + filename, ext))
110 self.assertEqual(posixpath.splitext(b"abc.def/" + path),
111 (b"abc.def/" + filename, ext))
112 self.assertEqual(posixpath.splitext(b"/abc.def/" + path),
113 (b"/abc.def/" + filename, ext))
114 self.assertEqual(posixpath.splitext(path + b"/"),
115 (filename + ext + b"/", b""))
Brett Cannonb47243a2003-06-16 21:54:50 +0000116
Guido van Rossumd8faa362007-04-27 19:54:29 +0000117 def test_splitext(self):
118 self.splitextTest("foo.bar", "foo", ".bar")
119 self.splitextTest("foo.boo.bar", "foo.boo", ".bar")
120 self.splitextTest("foo.boo.biff.bar", "foo.boo.biff", ".bar")
121 self.splitextTest(".csh.rc", ".csh", ".rc")
122 self.splitextTest("nodots", "nodots", "")
123 self.splitextTest(".cshrc", ".cshrc", "")
124 self.splitextTest("...manydots", "...manydots", "")
125 self.splitextTest("...manydots.ext", "...manydots", ".ext")
126 self.splitextTest(".", ".", "")
127 self.splitextTest("..", "..", "")
128 self.splitextTest("........", "........", "")
129 self.splitextTest("", "", "")
Brett Cannonb47243a2003-06-16 21:54:50 +0000130
131 def test_isabs(self):
132 self.assertIs(posixpath.isabs(""), False)
133 self.assertIs(posixpath.isabs("/"), True)
134 self.assertIs(posixpath.isabs("/foo"), True)
135 self.assertIs(posixpath.isabs("/foo/bar"), True)
136 self.assertIs(posixpath.isabs("foo/bar"), False)
137
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000138 self.assertIs(posixpath.isabs(b""), False)
139 self.assertIs(posixpath.isabs(b"/"), True)
140 self.assertIs(posixpath.isabs(b"/foo"), True)
141 self.assertIs(posixpath.isabs(b"/foo/bar"), True)
142 self.assertIs(posixpath.isabs(b"foo/bar"), False)
143
Brett Cannonb47243a2003-06-16 21:54:50 +0000144 def test_basename(self):
145 self.assertEqual(posixpath.basename("/foo/bar"), "bar")
146 self.assertEqual(posixpath.basename("/"), "")
147 self.assertEqual(posixpath.basename("foo"), "foo")
148 self.assertEqual(posixpath.basename("////foo"), "foo")
149 self.assertEqual(posixpath.basename("//foo//bar"), "bar")
150
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000151 self.assertEqual(posixpath.basename(b"/foo/bar"), b"bar")
152 self.assertEqual(posixpath.basename(b"/"), b"")
153 self.assertEqual(posixpath.basename(b"foo"), b"foo")
154 self.assertEqual(posixpath.basename(b"////foo"), b"foo")
155 self.assertEqual(posixpath.basename(b"//foo//bar"), b"bar")
156
Brett Cannonb47243a2003-06-16 21:54:50 +0000157 def test_dirname(self):
158 self.assertEqual(posixpath.dirname("/foo/bar"), "/foo")
159 self.assertEqual(posixpath.dirname("/"), "/")
160 self.assertEqual(posixpath.dirname("foo"), "")
161 self.assertEqual(posixpath.dirname("////foo"), "////")
162 self.assertEqual(posixpath.dirname("//foo//bar"), "//foo")
163
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000164 self.assertEqual(posixpath.dirname(b"/foo/bar"), b"/foo")
165 self.assertEqual(posixpath.dirname(b"/"), b"/")
166 self.assertEqual(posixpath.dirname(b"foo"), b"")
167 self.assertEqual(posixpath.dirname(b"////foo"), b"////")
168 self.assertEqual(posixpath.dirname(b"//foo//bar"), b"//foo")
169
Brett Cannonb47243a2003-06-16 21:54:50 +0000170 def test_islink(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000171 self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
Michael Foord07926f02011-03-16 17:19:16 -0400172 self.assertIs(posixpath.lexists(support.TESTFN + "2"), False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000173 f = open(support.TESTFN + "1", "wb")
Brett Cannonb47243a2003-06-16 21:54:50 +0000174 try:
Guido van Rossum7dcb8442007-08-27 23:26:56 +0000175 f.write(b"foo")
Brett Cannonb47243a2003-06-16 21:54:50 +0000176 f.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000177 self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
Brian Curtin3b4499c2010-12-28 14:31:47 +0000178 if support.can_symlink():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000179 os.symlink(support.TESTFN + "1", support.TESTFN + "2")
180 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
181 os.remove(support.TESTFN + "1")
182 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
183 self.assertIs(posixpath.exists(support.TESTFN + "2"), False)
184 self.assertIs(posixpath.lexists(support.TESTFN + "2"), True)
Brett Cannonb47243a2003-06-16 21:54:50 +0000185 finally:
186 if not f.close():
187 f.close()
Brett Cannonb47243a2003-06-16 21:54:50 +0000188
Brian Curtind40e6f72010-07-08 21:39:08 +0000189 @staticmethod
190 def _create_file(filename):
191 with open(filename, 'wb') as f:
192 f.write(b'foo')
193
Guido van Rossumd8faa362007-04-27 19:54:29 +0000194 def test_samefile(self):
Brian Curtind40e6f72010-07-08 21:39:08 +0000195 test_fn = support.TESTFN + "1"
196 self._create_file(test_fn)
197 self.assertTrue(posixpath.samefile(test_fn, test_fn))
198 self.assertRaises(TypeError, posixpath.samefile)
199
200 @unittest.skipIf(
201 sys.platform.startswith('win'),
202 "posixpath.samefile does not work on links in Windows")
Brian Curtin52173d42010-12-02 18:29:18 +0000203 @unittest.skipUnless(hasattr(os, "symlink"),
204 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000205 def test_samefile_on_links(self):
206 test_fn1 = support.TESTFN + "1"
207 test_fn2 = support.TESTFN + "2"
208 self._create_file(test_fn1)
209
210 os.symlink(test_fn1, test_fn2)
211 self.assertTrue(posixpath.samefile(test_fn1, test_fn2))
212 os.remove(test_fn2)
213
214 self._create_file(test_fn2)
215 self.assertFalse(posixpath.samefile(test_fn1, test_fn2))
216
Brett Cannonb47243a2003-06-16 21:54:50 +0000217
Brett Cannonb47243a2003-06-16 21:54:50 +0000218 def test_samestat(self):
Brian Curtind40e6f72010-07-08 21:39:08 +0000219 test_fn = support.TESTFN + "1"
220 self._create_file(test_fn)
221 test_fns = [test_fn]*2
222 stats = map(os.stat, test_fns)
223 self.assertTrue(posixpath.samestat(*stats))
224
225 @unittest.skipIf(
226 sys.platform.startswith('win'),
227 "posixpath.samestat does not work on links in Windows")
Brian Curtin52173d42010-12-02 18:29:18 +0000228 @unittest.skipUnless(hasattr(os, "symlink"),
229 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000230 def test_samestat_on_links(self):
231 test_fn1 = support.TESTFN + "1"
232 test_fn2 = support.TESTFN + "2"
Brian Curtin16633fa2010-07-09 13:54:27 +0000233 self._create_file(test_fn1)
Brian Curtind40e6f72010-07-08 21:39:08 +0000234 test_fns = (test_fn1, test_fn2)
235 os.symlink(*test_fns)
236 stats = map(os.stat, test_fns)
237 self.assertTrue(posixpath.samestat(*stats))
238 os.remove(test_fn2)
239
240 self._create_file(test_fn2)
241 stats = map(os.stat, test_fns)
242 self.assertFalse(posixpath.samestat(*stats))
243
244 self.assertRaises(TypeError, posixpath.samestat)
Brett Cannonb47243a2003-06-16 21:54:50 +0000245
Brett Cannonb47243a2003-06-16 21:54:50 +0000246 def test_ismount(self):
247 self.assertIs(posixpath.ismount("/"), True)
Michael Foord07926f02011-03-16 17:19:16 -0400248 self.assertIs(posixpath.ismount(b"/"), True)
249
250 def test_ismount_non_existent(self):
251 # Non-existent mountpoint.
252 self.assertIs(posixpath.ismount(ABSTFN), False)
253 try:
254 os.mkdir(ABSTFN)
255 self.assertIs(posixpath.ismount(ABSTFN), False)
256 finally:
257 safe_rmdir(ABSTFN)
258
259 @unittest.skipUnless(support.can_symlink(),
260 "Test requires symlink support")
261 def test_ismount_symlinks(self):
262 # Symlinks are never mountpoints.
263 try:
264 os.symlink("/", ABSTFN)
265 self.assertIs(posixpath.ismount(ABSTFN), False)
266 finally:
267 os.unlink(ABSTFN)
268
269 @unittest.skipIf(posix is None, "Test requires posix module")
270 def test_ismount_different_device(self):
271 # Simulate the path being on a different device from its parent by
272 # mocking out st_dev.
273 save_lstat = os.lstat
274 def fake_lstat(path):
275 st_ino = 0
276 st_dev = 0
277 if path == ABSTFN:
278 st_dev = 1
279 st_ino = 1
280 return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
281 try:
282 os.lstat = fake_lstat
283 self.assertIs(posixpath.ismount(ABSTFN), True)
284 finally:
285 os.lstat = save_lstat
Brett Cannonb47243a2003-06-16 21:54:50 +0000286
Brett Cannonb47243a2003-06-16 21:54:50 +0000287 def test_expanduser(self):
288 self.assertEqual(posixpath.expanduser("foo"), "foo")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000289 self.assertEqual(posixpath.expanduser(b"foo"), b"foo")
Brett Cannonb47243a2003-06-16 21:54:50 +0000290 try:
291 import pwd
292 except ImportError:
293 pass
294 else:
Ezio Melottie9615932010-01-24 19:26:24 +0000295 self.assertIsInstance(posixpath.expanduser("~/"), str)
296 self.assertIsInstance(posixpath.expanduser(b"~/"), bytes)
Neal Norwitz168e73d2003-07-01 03:33:31 +0000297 # if home directory == root directory, this test makes no sense
298 if posixpath.expanduser("~") != '/':
299 self.assertEqual(
300 posixpath.expanduser("~") + "/",
301 posixpath.expanduser("~/")
302 )
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000303 self.assertEqual(
304 posixpath.expanduser(b"~") + b"/",
305 posixpath.expanduser(b"~/")
306 )
Ezio Melottie9615932010-01-24 19:26:24 +0000307 self.assertIsInstance(posixpath.expanduser("~root/"), str)
308 self.assertIsInstance(posixpath.expanduser("~foo/"), str)
309 self.assertIsInstance(posixpath.expanduser(b"~root/"), bytes)
310 self.assertIsInstance(posixpath.expanduser(b"~foo/"), bytes)
Brett Cannonb47243a2003-06-16 21:54:50 +0000311
Hirokazu Yamamoto71959632009-04-27 01:44:28 +0000312 with support.EnvironmentVarGuard() as env:
Walter Dörwald155374d2009-05-01 19:58:58 +0000313 env['HOME'] = '/'
Walter Dörwaldb525e182009-04-26 21:39:21 +0000314 self.assertEqual(posixpath.expanduser("~"), "/")
Jesus Cea7f0d8882012-05-10 05:10:50 +0200315 self.assertEqual(posixpath.expanduser("~/foo"), "/foo")
Michael Foord07926f02011-03-16 17:19:16 -0400316 # expanduser should fall back to using the password database
317 del env['HOME']
318 home = pwd.getpwuid(os.getuid()).pw_dir
319 self.assertEqual(posixpath.expanduser("~"), home)
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000320
Brett Cannonb47243a2003-06-16 21:54:50 +0000321 def test_normpath(self):
322 self.assertEqual(posixpath.normpath(""), ".")
323 self.assertEqual(posixpath.normpath("/"), "/")
324 self.assertEqual(posixpath.normpath("//"), "//")
325 self.assertEqual(posixpath.normpath("///"), "/")
326 self.assertEqual(posixpath.normpath("///foo/.//bar//"), "/foo/bar")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000327 self.assertEqual(posixpath.normpath("///foo/.//bar//.//..//.//baz"),
328 "/foo/baz")
Brett Cannonb47243a2003-06-16 21:54:50 +0000329 self.assertEqual(posixpath.normpath("///..//./foo/.//bar"), "/foo/bar")
330
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000331 self.assertEqual(posixpath.normpath(b""), b".")
332 self.assertEqual(posixpath.normpath(b"/"), b"/")
333 self.assertEqual(posixpath.normpath(b"//"), b"//")
334 self.assertEqual(posixpath.normpath(b"///"), b"/")
335 self.assertEqual(posixpath.normpath(b"///foo/.//bar//"), b"/foo/bar")
336 self.assertEqual(posixpath.normpath(b"///foo/.//bar//.//..//.//baz"),
337 b"/foo/baz")
338 self.assertEqual(posixpath.normpath(b"///..//./foo/.//bar"),
339 b"/foo/bar")
340
Serhiy Storchaka1548ed62013-02-18 13:32:30 +0200341 @skip_if_ABSTFN_contains_backslash
Serhiy Storchaka467393d2013-02-18 12:21:04 +0200342 def test_realpath_curdir(self):
343 self.assertEqual(realpath('.'), os.getcwd())
344 self.assertEqual(realpath('./.'), os.getcwd())
345 self.assertEqual(realpath('/'.join(['.'] * 100)), os.getcwd())
346
347 self.assertEqual(realpath(b'.'), os.getcwdb())
348 self.assertEqual(realpath(b'./.'), os.getcwdb())
349 self.assertEqual(realpath(b'/'.join([b'.'] * 100)), os.getcwdb())
350
Serhiy Storchaka1548ed62013-02-18 13:32:30 +0200351 @skip_if_ABSTFN_contains_backslash
Serhiy Storchaka467393d2013-02-18 12:21:04 +0200352 def test_realpath_pardir(self):
353 self.assertEqual(realpath('..'), dirname(os.getcwd()))
354 self.assertEqual(realpath('../..'), dirname(dirname(os.getcwd())))
355 self.assertEqual(realpath('/'.join(['..'] * 100)), '/')
356
357 self.assertEqual(realpath(b'..'), dirname(os.getcwdb()))
358 self.assertEqual(realpath(b'../..'), dirname(dirname(os.getcwdb())))
359 self.assertEqual(realpath(b'/'.join([b'..'] * 100)), b'/')
360
Brian Curtin52173d42010-12-02 18:29:18 +0000361 @unittest.skipUnless(hasattr(os, "symlink"),
362 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000363 @skip_if_ABSTFN_contains_backslash
364 def test_realpath_basic(self):
365 # Basic operation.
366 try:
367 os.symlink(ABSTFN+"1", ABSTFN)
368 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
369 finally:
370 support.unlink(ABSTFN)
Tim Petersa45cacf2004-08-20 03:47:14 +0000371
Brian Curtin52173d42010-12-02 18:29:18 +0000372 @unittest.skipUnless(hasattr(os, "symlink"),
373 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000374 @skip_if_ABSTFN_contains_backslash
Michael Foord07926f02011-03-16 17:19:16 -0400375 def test_realpath_relative(self):
376 try:
377 os.symlink(posixpath.relpath(ABSTFN+"1"), ABSTFN)
378 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
379 finally:
380 support.unlink(ABSTFN)
381
382 @unittest.skipUnless(hasattr(os, "symlink"),
383 "Missing symlink implementation")
384 @skip_if_ABSTFN_contains_backslash
Brian Curtind40e6f72010-07-08 21:39:08 +0000385 def test_realpath_symlink_loops(self):
386 # Bug #930024, return the path unchanged if we get into an infinite
387 # symlink loop.
388 try:
389 old_path = abspath('.')
390 os.symlink(ABSTFN, ABSTFN)
391 self.assertEqual(realpath(ABSTFN), ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000392
Brian Curtind40e6f72010-07-08 21:39:08 +0000393 os.symlink(ABSTFN+"1", ABSTFN+"2")
394 os.symlink(ABSTFN+"2", ABSTFN+"1")
395 self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1")
396 self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000397
Serhiy Storchakadf326912013-02-10 12:22:07 +0200398 self.assertEqual(realpath(ABSTFN+"1/x"), ABSTFN+"1/x")
399 self.assertEqual(realpath(ABSTFN+"1/.."), dirname(ABSTFN))
400 self.assertEqual(realpath(ABSTFN+"1/../x"), dirname(ABSTFN) + "/x")
401 os.symlink(ABSTFN+"x", ABSTFN+"y")
402 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "y"),
403 ABSTFN + "y")
404 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "1"),
405 ABSTFN + "1")
406
407 os.symlink(basename(ABSTFN) + "a/b", ABSTFN+"a")
408 self.assertEqual(realpath(ABSTFN+"a"), ABSTFN+"a/b")
409
410 os.symlink("../" + basename(dirname(ABSTFN)) + "/" +
411 basename(ABSTFN) + "c", ABSTFN+"c")
412 self.assertEqual(realpath(ABSTFN+"c"), ABSTFN+"c")
413
Brian Curtind40e6f72010-07-08 21:39:08 +0000414 # Test using relative path as well.
415 os.chdir(dirname(ABSTFN))
416 self.assertEqual(realpath(basename(ABSTFN)), ABSTFN)
417 finally:
418 os.chdir(old_path)
419 support.unlink(ABSTFN)
420 support.unlink(ABSTFN+"1")
421 support.unlink(ABSTFN+"2")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200422 support.unlink(ABSTFN+"y")
423 support.unlink(ABSTFN+"c")
424
425 @unittest.skipUnless(hasattr(os, "symlink"),
426 "Missing symlink implementation")
427 @skip_if_ABSTFN_contains_backslash
428 def test_realpath_repeated_indirect_symlinks(self):
429 # Issue #6975.
430 try:
431 os.mkdir(ABSTFN)
432 os.symlink('../' + basename(ABSTFN), ABSTFN + '/self')
433 os.symlink('self/self/self', ABSTFN + '/link')
434 self.assertEqual(realpath(ABSTFN + '/link'), ABSTFN)
435 finally:
436 support.unlink(ABSTFN + '/self')
437 support.unlink(ABSTFN + '/link')
438 safe_rmdir(ABSTFN)
439
440 @unittest.skipUnless(hasattr(os, "symlink"),
441 "Missing symlink implementation")
442 @skip_if_ABSTFN_contains_backslash
443 def test_realpath_deep_recursion(self):
444 depth = 10
445 old_path = abspath('.')
446 try:
447 os.mkdir(ABSTFN)
448 for i in range(depth):
449 os.symlink('/'.join(['%d' % i] * 10), ABSTFN + '/%d' % (i + 1))
450 os.symlink('.', ABSTFN + '/0')
451 self.assertEqual(realpath(ABSTFN + '/%d' % depth), ABSTFN)
452
453 # Test using relative path as well.
454 os.chdir(ABSTFN)
455 self.assertEqual(realpath('%d' % depth), ABSTFN)
456 finally:
457 os.chdir(old_path)
458 for i in range(depth + 1):
459 support.unlink(ABSTFN + '/%d' % i)
460 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000461
Brian Curtin52173d42010-12-02 18:29:18 +0000462 @unittest.skipUnless(hasattr(os, "symlink"),
463 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000464 @skip_if_ABSTFN_contains_backslash
465 def test_realpath_resolve_parents(self):
466 # We also need to resolve any symlinks in the parents of a relative
467 # path passed to realpath. E.g.: current working directory is
468 # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call
469 # realpath("a"). This should return /usr/share/doc/a/.
470 try:
471 old_path = abspath('.')
472 os.mkdir(ABSTFN)
473 os.mkdir(ABSTFN + "/y")
474 os.symlink(ABSTFN + "/y", ABSTFN + "/k")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000475
Brian Curtind40e6f72010-07-08 21:39:08 +0000476 os.chdir(ABSTFN + "/k")
477 self.assertEqual(realpath("a"), ABSTFN + "/y/a")
478 finally:
479 os.chdir(old_path)
480 support.unlink(ABSTFN + "/k")
481 safe_rmdir(ABSTFN + "/y")
482 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000483
Brian Curtin52173d42010-12-02 18:29:18 +0000484 @unittest.skipUnless(hasattr(os, "symlink"),
485 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000486 @skip_if_ABSTFN_contains_backslash
487 def test_realpath_resolve_before_normalizing(self):
488 # Bug #990669: Symbolic links should be resolved before we
489 # normalize the path. E.g.: if we have directories 'a', 'k' and 'y'
490 # in the following hierarchy:
491 # a/k/y
492 #
493 # and a symbolic link 'link-y' pointing to 'y' in directory 'a',
494 # then realpath("link-y/..") should return 'k', not 'a'.
495 try:
496 old_path = abspath('.')
497 os.mkdir(ABSTFN)
498 os.mkdir(ABSTFN + "/k")
499 os.mkdir(ABSTFN + "/k/y")
500 os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000501
Brian Curtind40e6f72010-07-08 21:39:08 +0000502 # Absolute path.
503 self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k")
504 # Relative path.
505 os.chdir(dirname(ABSTFN))
506 self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."),
507 ABSTFN + "/k")
508 finally:
509 os.chdir(old_path)
510 support.unlink(ABSTFN + "/link-y")
511 safe_rmdir(ABSTFN + "/k/y")
512 safe_rmdir(ABSTFN + "/k")
513 safe_rmdir(ABSTFN)
Tim Peters5d36a552005-06-03 22:40:27 +0000514
Brian Curtin52173d42010-12-02 18:29:18 +0000515 @unittest.skipUnless(hasattr(os, "symlink"),
516 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000517 @skip_if_ABSTFN_contains_backslash
518 def test_realpath_resolve_first(self):
519 # Bug #1213894: The first component of the path, if not absolute,
520 # must be resolved too.
Georg Brandl268e61c2005-06-03 14:28:50 +0000521
Brian Curtind40e6f72010-07-08 21:39:08 +0000522 try:
523 old_path = abspath('.')
524 os.mkdir(ABSTFN)
525 os.mkdir(ABSTFN + "/k")
526 os.symlink(ABSTFN, ABSTFN + "link")
527 os.chdir(dirname(ABSTFN))
Tim Peters5d36a552005-06-03 22:40:27 +0000528
Brian Curtind40e6f72010-07-08 21:39:08 +0000529 base = basename(ABSTFN)
530 self.assertEqual(realpath(base + "link"), ABSTFN)
531 self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k")
532 finally:
533 os.chdir(old_path)
534 support.unlink(ABSTFN + "link")
535 safe_rmdir(ABSTFN + "/k")
536 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000537
Guido van Rossumd8faa362007-04-27 19:54:29 +0000538 def test_relpath(self):
539 (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar")
540 try:
541 curdir = os.path.split(os.getcwd())[-1]
542 self.assertRaises(ValueError, posixpath.relpath, "")
543 self.assertEqual(posixpath.relpath("a"), "a")
544 self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a")
545 self.assertEqual(posixpath.relpath("a/b"), "a/b")
546 self.assertEqual(posixpath.relpath("../a/b"), "../a/b")
547 self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000548 self.assertEqual(posixpath.relpath("a/b", "../c"),
549 "../"+curdir+"/a/b")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000550 self.assertEqual(posixpath.relpath("a", "b/c"), "../../a")
Christian Heimesfaf2f632008-01-06 16:59:19 +0000551 self.assertEqual(posixpath.relpath("a", "a"), ".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000552 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x/y/z"), '../../../foo/bar/bat')
553 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/foo/bar"), 'bat')
554 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/"), 'foo/bar/bat')
555 self.assertEqual(posixpath.relpath("/", "/foo/bar/bat"), '../../..')
556 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x"), '../foo/bar/bat')
557 self.assertEqual(posixpath.relpath("/x", "/foo/bar/bat"), '../../../x')
558 self.assertEqual(posixpath.relpath("/", "/"), '.')
559 self.assertEqual(posixpath.relpath("/a", "/a"), '.')
560 self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000561 finally:
562 os.getcwd = real_getcwd
Brett Cannonb47243a2003-06-16 21:54:50 +0000563
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000564 def test_relpath_bytes(self):
565 (real_getcwdb, os.getcwdb) = (os.getcwdb, lambda: br"/home/user/bar")
566 try:
567 curdir = os.path.split(os.getcwdb())[-1]
568 self.assertRaises(ValueError, posixpath.relpath, b"")
569 self.assertEqual(posixpath.relpath(b"a"), b"a")
570 self.assertEqual(posixpath.relpath(posixpath.abspath(b"a")), b"a")
571 self.assertEqual(posixpath.relpath(b"a/b"), b"a/b")
572 self.assertEqual(posixpath.relpath(b"../a/b"), b"../a/b")
573 self.assertEqual(posixpath.relpath(b"a", b"../b"),
574 b"../"+curdir+b"/a")
575 self.assertEqual(posixpath.relpath(b"a/b", b"../c"),
576 b"../"+curdir+b"/a/b")
577 self.assertEqual(posixpath.relpath(b"a", b"b/c"), b"../../a")
578 self.assertEqual(posixpath.relpath(b"a", b"a"), b".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000579 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x/y/z"), b'../../../foo/bar/bat')
580 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/foo/bar"), b'bat')
581 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/"), b'foo/bar/bat')
582 self.assertEqual(posixpath.relpath(b"/", b"/foo/bar/bat"), b'../../..')
583 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x"), b'../foo/bar/bat')
584 self.assertEqual(posixpath.relpath(b"/x", b"/foo/bar/bat"), b'../../../x')
585 self.assertEqual(posixpath.relpath(b"/", b"/"), b'.')
586 self.assertEqual(posixpath.relpath(b"/a", b"/a"), b'.')
587 self.assertEqual(posixpath.relpath(b"/a/b", b"/a/b"), b'.')
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000588
589 self.assertRaises(TypeError, posixpath.relpath, b"bytes", "str")
590 self.assertRaises(TypeError, posixpath.relpath, "str", b"bytes")
591 finally:
592 os.getcwdb = real_getcwdb
593
Michael Foord07926f02011-03-16 17:19:16 -0400594 def test_sameopenfile(self):
595 fname = support.TESTFN + "1"
596 with open(fname, "wb") as a, open(fname, "wb") as b:
597 self.assertTrue(posixpath.sameopenfile(a.fileno(), b.fileno()))
598
Florent Xiclunac9c79782010-03-08 12:24:53 +0000599
600class PosixCommonTest(test_genericpath.CommonTest):
601 pathmodule = posixpath
602 attributes = ['relpath', 'samefile', 'sameopenfile', 'samestat']
603
604
Brett Cannonb47243a2003-06-16 21:54:50 +0000605def test_main():
Florent Xiclunac9c79782010-03-08 12:24:53 +0000606 support.run_unittest(PosixPathTest, PosixCommonTest)
607
Brett Cannonb47243a2003-06-16 21:54:50 +0000608
609if __name__=="__main__":
610 test_main()