blob: 0e7d86648582efc1a12d6e35157fd5c503add857 [file] [log] [blame]
Hynek Schlawackc5a45662012-07-17 13:05:43 +02001import itertools
Brian Curtind40e6f72010-07-08 21:39:08 +00002import os
Victor Stinner1ab6c2d2011-11-15 22:27:41 +01003import posixpath
Brian Curtind40e6f72010-07-08 21:39:08 +00004import sys
Victor Stinner1ab6c2d2011-11-15 22:27:41 +01005import unittest
6import warnings
Georg Brandl89fad142010-03-14 10:23:39 +00007from posixpath import realpath, abspath, dirname, basename
Victor Stinner1ab6c2d2011-11-15 22:27:41 +01008from test import support, test_genericpath
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)
Victor Stinner1ab6c2d2011-11-15 22:27:41 +0100248 with warnings.catch_warnings():
249 warnings.simplefilter("ignore", DeprecationWarning)
250 self.assertIs(posixpath.ismount(b"/"), True)
Michael Foord07926f02011-03-16 17:19:16 -0400251
252 def test_ismount_non_existent(self):
253 # Non-existent mountpoint.
254 self.assertIs(posixpath.ismount(ABSTFN), False)
255 try:
256 os.mkdir(ABSTFN)
257 self.assertIs(posixpath.ismount(ABSTFN), False)
258 finally:
259 safe_rmdir(ABSTFN)
260
261 @unittest.skipUnless(support.can_symlink(),
262 "Test requires symlink support")
263 def test_ismount_symlinks(self):
264 # Symlinks are never mountpoints.
265 try:
266 os.symlink("/", ABSTFN)
267 self.assertIs(posixpath.ismount(ABSTFN), False)
268 finally:
269 os.unlink(ABSTFN)
270
271 @unittest.skipIf(posix is None, "Test requires posix module")
272 def test_ismount_different_device(self):
273 # Simulate the path being on a different device from its parent by
274 # mocking out st_dev.
275 save_lstat = os.lstat
276 def fake_lstat(path):
277 st_ino = 0
278 st_dev = 0
279 if path == ABSTFN:
280 st_dev = 1
281 st_ino = 1
282 return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
283 try:
284 os.lstat = fake_lstat
285 self.assertIs(posixpath.ismount(ABSTFN), True)
286 finally:
287 os.lstat = save_lstat
Brett Cannonb47243a2003-06-16 21:54:50 +0000288
Brett Cannonb47243a2003-06-16 21:54:50 +0000289 def test_expanduser(self):
290 self.assertEqual(posixpath.expanduser("foo"), "foo")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000291 self.assertEqual(posixpath.expanduser(b"foo"), b"foo")
Brett Cannonb47243a2003-06-16 21:54:50 +0000292 try:
293 import pwd
294 except ImportError:
295 pass
296 else:
Ezio Melottie9615932010-01-24 19:26:24 +0000297 self.assertIsInstance(posixpath.expanduser("~/"), str)
298 self.assertIsInstance(posixpath.expanduser(b"~/"), bytes)
Neal Norwitz168e73d2003-07-01 03:33:31 +0000299 # if home directory == root directory, this test makes no sense
300 if posixpath.expanduser("~") != '/':
301 self.assertEqual(
302 posixpath.expanduser("~") + "/",
303 posixpath.expanduser("~/")
304 )
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000305 self.assertEqual(
306 posixpath.expanduser(b"~") + b"/",
307 posixpath.expanduser(b"~/")
308 )
Ezio Melottie9615932010-01-24 19:26:24 +0000309 self.assertIsInstance(posixpath.expanduser("~root/"), str)
310 self.assertIsInstance(posixpath.expanduser("~foo/"), str)
311 self.assertIsInstance(posixpath.expanduser(b"~root/"), bytes)
312 self.assertIsInstance(posixpath.expanduser(b"~foo/"), bytes)
Brett Cannonb47243a2003-06-16 21:54:50 +0000313
Hirokazu Yamamoto71959632009-04-27 01:44:28 +0000314 with support.EnvironmentVarGuard() as env:
Walter Dörwald155374d2009-05-01 19:58:58 +0000315 env['HOME'] = '/'
Walter Dörwaldb525e182009-04-26 21:39:21 +0000316 self.assertEqual(posixpath.expanduser("~"), "/")
Jesus Cea7f0d8882012-05-10 05:10:50 +0200317 self.assertEqual(posixpath.expanduser("~/foo"), "/foo")
Michael Foord07926f02011-03-16 17:19:16 -0400318 # expanduser should fall back to using the password database
319 del env['HOME']
320 home = pwd.getpwuid(os.getuid()).pw_dir
Ezio Melottice82d572013-05-09 15:19:45 +0300321 # $HOME can end with a trailing /, so strip it (see #17809)
322 self.assertEqual(posixpath.expanduser("~"), home.rstrip("/"))
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000323
Brett Cannonb47243a2003-06-16 21:54:50 +0000324 def test_normpath(self):
325 self.assertEqual(posixpath.normpath(""), ".")
326 self.assertEqual(posixpath.normpath("/"), "/")
327 self.assertEqual(posixpath.normpath("//"), "//")
328 self.assertEqual(posixpath.normpath("///"), "/")
329 self.assertEqual(posixpath.normpath("///foo/.//bar//"), "/foo/bar")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000330 self.assertEqual(posixpath.normpath("///foo/.//bar//.//..//.//baz"),
331 "/foo/baz")
Brett Cannonb47243a2003-06-16 21:54:50 +0000332 self.assertEqual(posixpath.normpath("///..//./foo/.//bar"), "/foo/bar")
333
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000334 self.assertEqual(posixpath.normpath(b""), b".")
335 self.assertEqual(posixpath.normpath(b"/"), b"/")
336 self.assertEqual(posixpath.normpath(b"//"), b"//")
337 self.assertEqual(posixpath.normpath(b"///"), b"/")
338 self.assertEqual(posixpath.normpath(b"///foo/.//bar//"), b"/foo/bar")
339 self.assertEqual(posixpath.normpath(b"///foo/.//bar//.//..//.//baz"),
340 b"/foo/baz")
341 self.assertEqual(posixpath.normpath(b"///..//./foo/.//bar"),
342 b"/foo/bar")
343
Serhiy Storchaka1548ed62013-02-18 13:32:30 +0200344 @skip_if_ABSTFN_contains_backslash
Serhiy Storchaka467393d2013-02-18 12:21:04 +0200345 def test_realpath_curdir(self):
346 self.assertEqual(realpath('.'), os.getcwd())
347 self.assertEqual(realpath('./.'), os.getcwd())
348 self.assertEqual(realpath('/'.join(['.'] * 100)), os.getcwd())
349
350 self.assertEqual(realpath(b'.'), os.getcwdb())
351 self.assertEqual(realpath(b'./.'), os.getcwdb())
352 self.assertEqual(realpath(b'/'.join([b'.'] * 100)), os.getcwdb())
353
Serhiy Storchaka1548ed62013-02-18 13:32:30 +0200354 @skip_if_ABSTFN_contains_backslash
Serhiy Storchaka467393d2013-02-18 12:21:04 +0200355 def test_realpath_pardir(self):
356 self.assertEqual(realpath('..'), dirname(os.getcwd()))
357 self.assertEqual(realpath('../..'), dirname(dirname(os.getcwd())))
358 self.assertEqual(realpath('/'.join(['..'] * 100)), '/')
359
360 self.assertEqual(realpath(b'..'), dirname(os.getcwdb()))
361 self.assertEqual(realpath(b'../..'), dirname(dirname(os.getcwdb())))
362 self.assertEqual(realpath(b'/'.join([b'..'] * 100)), b'/')
363
Brian Curtin52173d42010-12-02 18:29:18 +0000364 @unittest.skipUnless(hasattr(os, "symlink"),
365 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000366 @skip_if_ABSTFN_contains_backslash
367 def test_realpath_basic(self):
368 # Basic operation.
369 try:
370 os.symlink(ABSTFN+"1", ABSTFN)
371 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
372 finally:
373 support.unlink(ABSTFN)
Tim Petersa45cacf2004-08-20 03:47:14 +0000374
Brian Curtin52173d42010-12-02 18:29:18 +0000375 @unittest.skipUnless(hasattr(os, "symlink"),
376 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000377 @skip_if_ABSTFN_contains_backslash
Michael Foord07926f02011-03-16 17:19:16 -0400378 def test_realpath_relative(self):
379 try:
380 os.symlink(posixpath.relpath(ABSTFN+"1"), ABSTFN)
381 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
382 finally:
383 support.unlink(ABSTFN)
384
385 @unittest.skipUnless(hasattr(os, "symlink"),
386 "Missing symlink implementation")
387 @skip_if_ABSTFN_contains_backslash
Brian Curtind40e6f72010-07-08 21:39:08 +0000388 def test_realpath_symlink_loops(self):
389 # Bug #930024, return the path unchanged if we get into an infinite
390 # symlink loop.
391 try:
392 old_path = abspath('.')
393 os.symlink(ABSTFN, ABSTFN)
394 self.assertEqual(realpath(ABSTFN), ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000395
Brian Curtind40e6f72010-07-08 21:39:08 +0000396 os.symlink(ABSTFN+"1", ABSTFN+"2")
397 os.symlink(ABSTFN+"2", ABSTFN+"1")
398 self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1")
399 self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000400
Serhiy Storchakadf326912013-02-10 12:22:07 +0200401 self.assertEqual(realpath(ABSTFN+"1/x"), ABSTFN+"1/x")
402 self.assertEqual(realpath(ABSTFN+"1/.."), dirname(ABSTFN))
403 self.assertEqual(realpath(ABSTFN+"1/../x"), dirname(ABSTFN) + "/x")
404 os.symlink(ABSTFN+"x", ABSTFN+"y")
405 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "y"),
406 ABSTFN + "y")
407 self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "1"),
408 ABSTFN + "1")
409
410 os.symlink(basename(ABSTFN) + "a/b", ABSTFN+"a")
411 self.assertEqual(realpath(ABSTFN+"a"), ABSTFN+"a/b")
412
413 os.symlink("../" + basename(dirname(ABSTFN)) + "/" +
414 basename(ABSTFN) + "c", ABSTFN+"c")
415 self.assertEqual(realpath(ABSTFN+"c"), ABSTFN+"c")
416
Brian Curtind40e6f72010-07-08 21:39:08 +0000417 # Test using relative path as well.
418 os.chdir(dirname(ABSTFN))
419 self.assertEqual(realpath(basename(ABSTFN)), ABSTFN)
420 finally:
421 os.chdir(old_path)
422 support.unlink(ABSTFN)
423 support.unlink(ABSTFN+"1")
424 support.unlink(ABSTFN+"2")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200425 support.unlink(ABSTFN+"y")
426 support.unlink(ABSTFN+"c")
Ezio Melotti136726c2013-03-01 20:59:17 +0200427 support.unlink(ABSTFN+"a")
Serhiy Storchakadf326912013-02-10 12:22:07 +0200428
429 @unittest.skipUnless(hasattr(os, "symlink"),
430 "Missing symlink implementation")
431 @skip_if_ABSTFN_contains_backslash
432 def test_realpath_repeated_indirect_symlinks(self):
433 # Issue #6975.
434 try:
435 os.mkdir(ABSTFN)
436 os.symlink('../' + basename(ABSTFN), ABSTFN + '/self')
437 os.symlink('self/self/self', ABSTFN + '/link')
438 self.assertEqual(realpath(ABSTFN + '/link'), ABSTFN)
439 finally:
440 support.unlink(ABSTFN + '/self')
441 support.unlink(ABSTFN + '/link')
442 safe_rmdir(ABSTFN)
443
444 @unittest.skipUnless(hasattr(os, "symlink"),
445 "Missing symlink implementation")
446 @skip_if_ABSTFN_contains_backslash
447 def test_realpath_deep_recursion(self):
448 depth = 10
449 old_path = abspath('.')
450 try:
451 os.mkdir(ABSTFN)
452 for i in range(depth):
453 os.symlink('/'.join(['%d' % i] * 10), ABSTFN + '/%d' % (i + 1))
454 os.symlink('.', ABSTFN + '/0')
455 self.assertEqual(realpath(ABSTFN + '/%d' % depth), ABSTFN)
456
457 # Test using relative path as well.
458 os.chdir(ABSTFN)
459 self.assertEqual(realpath('%d' % depth), ABSTFN)
460 finally:
461 os.chdir(old_path)
462 for i in range(depth + 1):
463 support.unlink(ABSTFN + '/%d' % i)
464 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000465
Brian Curtin52173d42010-12-02 18:29:18 +0000466 @unittest.skipUnless(hasattr(os, "symlink"),
467 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000468 @skip_if_ABSTFN_contains_backslash
469 def test_realpath_resolve_parents(self):
470 # We also need to resolve any symlinks in the parents of a relative
471 # path passed to realpath. E.g.: current working directory is
472 # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call
473 # realpath("a"). This should return /usr/share/doc/a/.
474 try:
475 old_path = abspath('.')
476 os.mkdir(ABSTFN)
477 os.mkdir(ABSTFN + "/y")
478 os.symlink(ABSTFN + "/y", ABSTFN + "/k")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000479
Brian Curtind40e6f72010-07-08 21:39:08 +0000480 os.chdir(ABSTFN + "/k")
481 self.assertEqual(realpath("a"), ABSTFN + "/y/a")
482 finally:
483 os.chdir(old_path)
484 support.unlink(ABSTFN + "/k")
485 safe_rmdir(ABSTFN + "/y")
486 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000487
Brian Curtin52173d42010-12-02 18:29:18 +0000488 @unittest.skipUnless(hasattr(os, "symlink"),
489 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000490 @skip_if_ABSTFN_contains_backslash
491 def test_realpath_resolve_before_normalizing(self):
492 # Bug #990669: Symbolic links should be resolved before we
493 # normalize the path. E.g.: if we have directories 'a', 'k' and 'y'
494 # in the following hierarchy:
495 # a/k/y
496 #
497 # and a symbolic link 'link-y' pointing to 'y' in directory 'a',
498 # then realpath("link-y/..") should return 'k', not 'a'.
499 try:
500 old_path = abspath('.')
501 os.mkdir(ABSTFN)
502 os.mkdir(ABSTFN + "/k")
503 os.mkdir(ABSTFN + "/k/y")
504 os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000505
Brian Curtind40e6f72010-07-08 21:39:08 +0000506 # Absolute path.
507 self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k")
508 # Relative path.
509 os.chdir(dirname(ABSTFN))
510 self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."),
511 ABSTFN + "/k")
512 finally:
513 os.chdir(old_path)
514 support.unlink(ABSTFN + "/link-y")
515 safe_rmdir(ABSTFN + "/k/y")
516 safe_rmdir(ABSTFN + "/k")
517 safe_rmdir(ABSTFN)
Tim Peters5d36a552005-06-03 22:40:27 +0000518
Brian Curtin52173d42010-12-02 18:29:18 +0000519 @unittest.skipUnless(hasattr(os, "symlink"),
520 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000521 @skip_if_ABSTFN_contains_backslash
522 def test_realpath_resolve_first(self):
523 # Bug #1213894: The first component of the path, if not absolute,
524 # must be resolved too.
Georg Brandl268e61c2005-06-03 14:28:50 +0000525
Brian Curtind40e6f72010-07-08 21:39:08 +0000526 try:
527 old_path = abspath('.')
528 os.mkdir(ABSTFN)
529 os.mkdir(ABSTFN + "/k")
530 os.symlink(ABSTFN, ABSTFN + "link")
531 os.chdir(dirname(ABSTFN))
Tim Peters5d36a552005-06-03 22:40:27 +0000532
Brian Curtind40e6f72010-07-08 21:39:08 +0000533 base = basename(ABSTFN)
534 self.assertEqual(realpath(base + "link"), ABSTFN)
535 self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k")
536 finally:
537 os.chdir(old_path)
538 support.unlink(ABSTFN + "link")
539 safe_rmdir(ABSTFN + "/k")
540 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000541
Guido van Rossumd8faa362007-04-27 19:54:29 +0000542 def test_relpath(self):
543 (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar")
544 try:
545 curdir = os.path.split(os.getcwd())[-1]
546 self.assertRaises(ValueError, posixpath.relpath, "")
547 self.assertEqual(posixpath.relpath("a"), "a")
548 self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a")
549 self.assertEqual(posixpath.relpath("a/b"), "a/b")
550 self.assertEqual(posixpath.relpath("../a/b"), "../a/b")
551 self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000552 self.assertEqual(posixpath.relpath("a/b", "../c"),
553 "../"+curdir+"/a/b")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000554 self.assertEqual(posixpath.relpath("a", "b/c"), "../../a")
Christian Heimesfaf2f632008-01-06 16:59:19 +0000555 self.assertEqual(posixpath.relpath("a", "a"), ".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000556 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x/y/z"), '../../../foo/bar/bat')
557 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/foo/bar"), 'bat')
558 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/"), 'foo/bar/bat')
559 self.assertEqual(posixpath.relpath("/", "/foo/bar/bat"), '../../..')
560 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x"), '../foo/bar/bat')
561 self.assertEqual(posixpath.relpath("/x", "/foo/bar/bat"), '../../../x')
562 self.assertEqual(posixpath.relpath("/", "/"), '.')
563 self.assertEqual(posixpath.relpath("/a", "/a"), '.')
564 self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000565 finally:
566 os.getcwd = real_getcwd
Brett Cannonb47243a2003-06-16 21:54:50 +0000567
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000568 def test_relpath_bytes(self):
569 (real_getcwdb, os.getcwdb) = (os.getcwdb, lambda: br"/home/user/bar")
570 try:
571 curdir = os.path.split(os.getcwdb())[-1]
572 self.assertRaises(ValueError, posixpath.relpath, b"")
573 self.assertEqual(posixpath.relpath(b"a"), b"a")
574 self.assertEqual(posixpath.relpath(posixpath.abspath(b"a")), b"a")
575 self.assertEqual(posixpath.relpath(b"a/b"), b"a/b")
576 self.assertEqual(posixpath.relpath(b"../a/b"), b"../a/b")
577 self.assertEqual(posixpath.relpath(b"a", b"../b"),
578 b"../"+curdir+b"/a")
579 self.assertEqual(posixpath.relpath(b"a/b", b"../c"),
580 b"../"+curdir+b"/a/b")
581 self.assertEqual(posixpath.relpath(b"a", b"b/c"), b"../../a")
582 self.assertEqual(posixpath.relpath(b"a", b"a"), b".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000583 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x/y/z"), b'../../../foo/bar/bat')
584 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/foo/bar"), b'bat')
585 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/"), b'foo/bar/bat')
586 self.assertEqual(posixpath.relpath(b"/", b"/foo/bar/bat"), b'../../..')
587 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x"), b'../foo/bar/bat')
588 self.assertEqual(posixpath.relpath(b"/x", b"/foo/bar/bat"), b'../../../x')
589 self.assertEqual(posixpath.relpath(b"/", b"/"), b'.')
590 self.assertEqual(posixpath.relpath(b"/a", b"/a"), b'.')
591 self.assertEqual(posixpath.relpath(b"/a/b", b"/a/b"), b'.')
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000592
593 self.assertRaises(TypeError, posixpath.relpath, b"bytes", "str")
594 self.assertRaises(TypeError, posixpath.relpath, "str", b"bytes")
595 finally:
596 os.getcwdb = real_getcwdb
597
Michael Foord07926f02011-03-16 17:19:16 -0400598 def test_sameopenfile(self):
599 fname = support.TESTFN + "1"
600 with open(fname, "wb") as a, open(fname, "wb") as b:
601 self.assertTrue(posixpath.sameopenfile(a.fileno(), b.fileno()))
602
Florent Xiclunac9c79782010-03-08 12:24:53 +0000603
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200604class PosixCommonTest(test_genericpath.CommonTest, unittest.TestCase):
Florent Xiclunac9c79782010-03-08 12:24:53 +0000605 pathmodule = posixpath
606 attributes = ['relpath', 'samefile', 'sameopenfile', 'samestat']
607
608
Brett Cannonb47243a2003-06-16 21:54:50 +0000609if __name__=="__main__":
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200610 unittest.main()