blob: 575e407d4352ed27f2d89b432f3a55e123922d9f [file] [log] [blame]
Brian Curtind40e6f72010-07-08 21:39:08 +00001import os
Victor Stinner1ab6c2d2011-11-15 22:27:41 +01002import posixpath
Brian Curtind40e6f72010-07-08 21:39:08 +00003import sys
Victor Stinner1ab6c2d2011-11-15 22:27:41 +01004import unittest
5import warnings
Georg Brandl89fad142010-03-14 10:23:39 +00006from posixpath import realpath, abspath, dirname, basename
Victor Stinner1ab6c2d2011-11-15 22:27:41 +01007from test import support, test_genericpath
Johannes Gijsbers4ec40642004-08-14 15:01:53 +00008
Michael Foord07926f02011-03-16 17:19:16 -04009try:
10 import posix
11except ImportError:
12 posix = None
13
Johannes Gijsbers4ec40642004-08-14 15:01:53 +000014# An absolute path to a temporary filename for testing. We can't rely on TESTFN
15# being an absolute path, so we need this.
16
Benjamin Petersonee8712c2008-05-20 21:35:26 +000017ABSTFN = abspath(support.TESTFN)
Skip Montanaroe809b002000-07-12 00:20:08 +000018
Brian Curtind40e6f72010-07-08 21:39:08 +000019def skip_if_ABSTFN_contains_backslash(test):
20 """
21 On Windows, posixpath.abspath still returns paths with backslashes
22 instead of posix forward slashes. If this is the case, several tests
23 fail, so skip them.
24 """
25 found_backslash = '\\' in ABSTFN
26 msg = "ABSTFN is not a posix path - tests fail"
27 return [test, unittest.skip(msg)(test)][found_backslash]
28
Guido van Rossumd8faa362007-04-27 19:54:29 +000029def safe_rmdir(dirname):
30 try:
31 os.rmdir(dirname)
32 except OSError:
33 pass
34
Brett Cannonb47243a2003-06-16 21:54:50 +000035class PosixPathTest(unittest.TestCase):
Skip Montanaroe809b002000-07-12 00:20:08 +000036
Guido van Rossumd8faa362007-04-27 19:54:29 +000037 def setUp(self):
38 self.tearDown()
39
40 def tearDown(self):
41 for suffix in ["", "1", "2"]:
Benjamin Petersonee8712c2008-05-20 21:35:26 +000042 support.unlink(support.TESTFN + suffix)
43 safe_rmdir(support.TESTFN + suffix)
Guido van Rossumd8faa362007-04-27 19:54:29 +000044
Brett Cannonb47243a2003-06-16 21:54:50 +000045 def test_join(self):
Guido van Rossumf0af3e32008-10-02 18:55:37 +000046 self.assertEqual(posixpath.join("/foo", "bar", "/bar", "baz"),
47 "/bar/baz")
Brett Cannonb47243a2003-06-16 21:54:50 +000048 self.assertEqual(posixpath.join("/foo", "bar", "baz"), "/foo/bar/baz")
Guido van Rossumf0af3e32008-10-02 18:55:37 +000049 self.assertEqual(posixpath.join("/foo/", "bar/", "baz/"),
50 "/foo/bar/baz/")
51
52 self.assertEqual(posixpath.join(b"/foo", b"bar", b"/bar", b"baz"),
53 b"/bar/baz")
54 self.assertEqual(posixpath.join(b"/foo", b"bar", b"baz"),
55 b"/foo/bar/baz")
56 self.assertEqual(posixpath.join(b"/foo/", b"bar/", b"baz/"),
57 b"/foo/bar/baz/")
Skip Montanaroe809b002000-07-12 00:20:08 +000058
Hynek Schlawack47749462012-07-15 16:21:30 +020059 with self.assertRaises(TypeError) as e:
60 posixpath.join(b'bytes', 'str')
61 self.assertIn("Can't mix strings and bytes", e.args[0])
62 with self.assertRaises(TypeError) as e:
63 posixpath.join('str', b'bytes')
64 self.assertIn("Can't mix strings and bytes", e.args[0])
65 with self.assertRaises(TypeError) as e:
66 posixpath.join('str', bytearray(b'bytes'))
67 self.assertIn("Can't mix strings and bytes", e.args[0])
Skip Montanaroe809b002000-07-12 00:20:08 +000068
Brett Cannonb47243a2003-06-16 21:54:50 +000069 def test_split(self):
70 self.assertEqual(posixpath.split("/foo/bar"), ("/foo", "bar"))
71 self.assertEqual(posixpath.split("/"), ("/", ""))
72 self.assertEqual(posixpath.split("foo"), ("", "foo"))
73 self.assertEqual(posixpath.split("////foo"), ("////", "foo"))
74 self.assertEqual(posixpath.split("//foo//bar"), ("//foo", "bar"))
75
Guido van Rossumf0af3e32008-10-02 18:55:37 +000076 self.assertEqual(posixpath.split(b"/foo/bar"), (b"/foo", b"bar"))
77 self.assertEqual(posixpath.split(b"/"), (b"/", b""))
78 self.assertEqual(posixpath.split(b"foo"), (b"", b"foo"))
79 self.assertEqual(posixpath.split(b"////foo"), (b"////", b"foo"))
80 self.assertEqual(posixpath.split(b"//foo//bar"), (b"//foo", b"bar"))
81
Guido van Rossumd8faa362007-04-27 19:54:29 +000082 def splitextTest(self, path, filename, ext):
83 self.assertEqual(posixpath.splitext(path), (filename, ext))
84 self.assertEqual(posixpath.splitext("/" + path), ("/" + filename, ext))
Guido van Rossumf0af3e32008-10-02 18:55:37 +000085 self.assertEqual(posixpath.splitext("abc/" + path),
86 ("abc/" + filename, ext))
87 self.assertEqual(posixpath.splitext("abc.def/" + path),
88 ("abc.def/" + filename, ext))
89 self.assertEqual(posixpath.splitext("/abc.def/" + path),
90 ("/abc.def/" + filename, ext))
91 self.assertEqual(posixpath.splitext(path + "/"),
92 (filename + ext + "/", ""))
93
94 path = bytes(path, "ASCII")
95 filename = bytes(filename, "ASCII")
96 ext = bytes(ext, "ASCII")
97
98 self.assertEqual(posixpath.splitext(path), (filename, ext))
99 self.assertEqual(posixpath.splitext(b"/" + path),
100 (b"/" + filename, ext))
101 self.assertEqual(posixpath.splitext(b"abc/" + path),
102 (b"abc/" + filename, ext))
103 self.assertEqual(posixpath.splitext(b"abc.def/" + path),
104 (b"abc.def/" + filename, ext))
105 self.assertEqual(posixpath.splitext(b"/abc.def/" + path),
106 (b"/abc.def/" + filename, ext))
107 self.assertEqual(posixpath.splitext(path + b"/"),
108 (filename + ext + b"/", b""))
Brett Cannonb47243a2003-06-16 21:54:50 +0000109
Guido van Rossumd8faa362007-04-27 19:54:29 +0000110 def test_splitext(self):
111 self.splitextTest("foo.bar", "foo", ".bar")
112 self.splitextTest("foo.boo.bar", "foo.boo", ".bar")
113 self.splitextTest("foo.boo.biff.bar", "foo.boo.biff", ".bar")
114 self.splitextTest(".csh.rc", ".csh", ".rc")
115 self.splitextTest("nodots", "nodots", "")
116 self.splitextTest(".cshrc", ".cshrc", "")
117 self.splitextTest("...manydots", "...manydots", "")
118 self.splitextTest("...manydots.ext", "...manydots", ".ext")
119 self.splitextTest(".", ".", "")
120 self.splitextTest("..", "..", "")
121 self.splitextTest("........", "........", "")
122 self.splitextTest("", "", "")
Brett Cannonb47243a2003-06-16 21:54:50 +0000123
124 def test_isabs(self):
125 self.assertIs(posixpath.isabs(""), False)
126 self.assertIs(posixpath.isabs("/"), True)
127 self.assertIs(posixpath.isabs("/foo"), True)
128 self.assertIs(posixpath.isabs("/foo/bar"), True)
129 self.assertIs(posixpath.isabs("foo/bar"), False)
130
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000131 self.assertIs(posixpath.isabs(b""), False)
132 self.assertIs(posixpath.isabs(b"/"), True)
133 self.assertIs(posixpath.isabs(b"/foo"), True)
134 self.assertIs(posixpath.isabs(b"/foo/bar"), True)
135 self.assertIs(posixpath.isabs(b"foo/bar"), False)
136
Brett Cannonb47243a2003-06-16 21:54:50 +0000137 def test_basename(self):
138 self.assertEqual(posixpath.basename("/foo/bar"), "bar")
139 self.assertEqual(posixpath.basename("/"), "")
140 self.assertEqual(posixpath.basename("foo"), "foo")
141 self.assertEqual(posixpath.basename("////foo"), "foo")
142 self.assertEqual(posixpath.basename("//foo//bar"), "bar")
143
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000144 self.assertEqual(posixpath.basename(b"/foo/bar"), b"bar")
145 self.assertEqual(posixpath.basename(b"/"), b"")
146 self.assertEqual(posixpath.basename(b"foo"), b"foo")
147 self.assertEqual(posixpath.basename(b"////foo"), b"foo")
148 self.assertEqual(posixpath.basename(b"//foo//bar"), b"bar")
149
Brett Cannonb47243a2003-06-16 21:54:50 +0000150 def test_dirname(self):
151 self.assertEqual(posixpath.dirname("/foo/bar"), "/foo")
152 self.assertEqual(posixpath.dirname("/"), "/")
153 self.assertEqual(posixpath.dirname("foo"), "")
154 self.assertEqual(posixpath.dirname("////foo"), "////")
155 self.assertEqual(posixpath.dirname("//foo//bar"), "//foo")
156
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000157 self.assertEqual(posixpath.dirname(b"/foo/bar"), b"/foo")
158 self.assertEqual(posixpath.dirname(b"/"), b"/")
159 self.assertEqual(posixpath.dirname(b"foo"), b"")
160 self.assertEqual(posixpath.dirname(b"////foo"), b"////")
161 self.assertEqual(posixpath.dirname(b"//foo//bar"), b"//foo")
162
Brett Cannonb47243a2003-06-16 21:54:50 +0000163 def test_islink(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000164 self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
Michael Foord07926f02011-03-16 17:19:16 -0400165 self.assertIs(posixpath.lexists(support.TESTFN + "2"), False)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000166 f = open(support.TESTFN + "1", "wb")
Brett Cannonb47243a2003-06-16 21:54:50 +0000167 try:
Guido van Rossum7dcb8442007-08-27 23:26:56 +0000168 f.write(b"foo")
Brett Cannonb47243a2003-06-16 21:54:50 +0000169 f.close()
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000170 self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
Brian Curtin3b4499c2010-12-28 14:31:47 +0000171 if support.can_symlink():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000172 os.symlink(support.TESTFN + "1", support.TESTFN + "2")
173 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
174 os.remove(support.TESTFN + "1")
175 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
176 self.assertIs(posixpath.exists(support.TESTFN + "2"), False)
177 self.assertIs(posixpath.lexists(support.TESTFN + "2"), True)
Brett Cannonb47243a2003-06-16 21:54:50 +0000178 finally:
179 if not f.close():
180 f.close()
Brett Cannonb47243a2003-06-16 21:54:50 +0000181
Brian Curtind40e6f72010-07-08 21:39:08 +0000182 @staticmethod
183 def _create_file(filename):
184 with open(filename, 'wb') as f:
185 f.write(b'foo')
186
Guido van Rossumd8faa362007-04-27 19:54:29 +0000187 def test_samefile(self):
Brian Curtind40e6f72010-07-08 21:39:08 +0000188 test_fn = support.TESTFN + "1"
189 self._create_file(test_fn)
190 self.assertTrue(posixpath.samefile(test_fn, test_fn))
191 self.assertRaises(TypeError, posixpath.samefile)
192
193 @unittest.skipIf(
194 sys.platform.startswith('win'),
195 "posixpath.samefile does not work on links in Windows")
Brian Curtin52173d42010-12-02 18:29:18 +0000196 @unittest.skipUnless(hasattr(os, "symlink"),
197 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000198 def test_samefile_on_links(self):
199 test_fn1 = support.TESTFN + "1"
200 test_fn2 = support.TESTFN + "2"
201 self._create_file(test_fn1)
202
203 os.symlink(test_fn1, test_fn2)
204 self.assertTrue(posixpath.samefile(test_fn1, test_fn2))
205 os.remove(test_fn2)
206
207 self._create_file(test_fn2)
208 self.assertFalse(posixpath.samefile(test_fn1, test_fn2))
209
Brett Cannonb47243a2003-06-16 21:54:50 +0000210
Brett Cannonb47243a2003-06-16 21:54:50 +0000211 def test_samestat(self):
Brian Curtind40e6f72010-07-08 21:39:08 +0000212 test_fn = support.TESTFN + "1"
213 self._create_file(test_fn)
214 test_fns = [test_fn]*2
215 stats = map(os.stat, test_fns)
216 self.assertTrue(posixpath.samestat(*stats))
217
218 @unittest.skipIf(
219 sys.platform.startswith('win'),
220 "posixpath.samestat does not work on links in Windows")
Brian Curtin52173d42010-12-02 18:29:18 +0000221 @unittest.skipUnless(hasattr(os, "symlink"),
222 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000223 def test_samestat_on_links(self):
224 test_fn1 = support.TESTFN + "1"
225 test_fn2 = support.TESTFN + "2"
Brian Curtin16633fa2010-07-09 13:54:27 +0000226 self._create_file(test_fn1)
Brian Curtind40e6f72010-07-08 21:39:08 +0000227 test_fns = (test_fn1, test_fn2)
228 os.symlink(*test_fns)
229 stats = map(os.stat, test_fns)
230 self.assertTrue(posixpath.samestat(*stats))
231 os.remove(test_fn2)
232
233 self._create_file(test_fn2)
234 stats = map(os.stat, test_fns)
235 self.assertFalse(posixpath.samestat(*stats))
236
237 self.assertRaises(TypeError, posixpath.samestat)
Brett Cannonb47243a2003-06-16 21:54:50 +0000238
Brett Cannonb47243a2003-06-16 21:54:50 +0000239 def test_ismount(self):
240 self.assertIs(posixpath.ismount("/"), True)
Victor Stinner1ab6c2d2011-11-15 22:27:41 +0100241 with warnings.catch_warnings():
242 warnings.simplefilter("ignore", DeprecationWarning)
243 self.assertIs(posixpath.ismount(b"/"), True)
Michael Foord07926f02011-03-16 17:19:16 -0400244
245 def test_ismount_non_existent(self):
246 # Non-existent mountpoint.
247 self.assertIs(posixpath.ismount(ABSTFN), False)
248 try:
249 os.mkdir(ABSTFN)
250 self.assertIs(posixpath.ismount(ABSTFN), False)
251 finally:
252 safe_rmdir(ABSTFN)
253
254 @unittest.skipUnless(support.can_symlink(),
255 "Test requires symlink support")
256 def test_ismount_symlinks(self):
257 # Symlinks are never mountpoints.
258 try:
259 os.symlink("/", ABSTFN)
260 self.assertIs(posixpath.ismount(ABSTFN), False)
261 finally:
262 os.unlink(ABSTFN)
263
264 @unittest.skipIf(posix is None, "Test requires posix module")
265 def test_ismount_different_device(self):
266 # Simulate the path being on a different device from its parent by
267 # mocking out st_dev.
268 save_lstat = os.lstat
269 def fake_lstat(path):
270 st_ino = 0
271 st_dev = 0
272 if path == ABSTFN:
273 st_dev = 1
274 st_ino = 1
275 return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
276 try:
277 os.lstat = fake_lstat
278 self.assertIs(posixpath.ismount(ABSTFN), True)
279 finally:
280 os.lstat = save_lstat
Brett Cannonb47243a2003-06-16 21:54:50 +0000281
Brett Cannonb47243a2003-06-16 21:54:50 +0000282 def test_expanduser(self):
283 self.assertEqual(posixpath.expanduser("foo"), "foo")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000284 self.assertEqual(posixpath.expanduser(b"foo"), b"foo")
Brett Cannonb47243a2003-06-16 21:54:50 +0000285 try:
286 import pwd
287 except ImportError:
288 pass
289 else:
Ezio Melottie9615932010-01-24 19:26:24 +0000290 self.assertIsInstance(posixpath.expanduser("~/"), str)
291 self.assertIsInstance(posixpath.expanduser(b"~/"), bytes)
Neal Norwitz168e73d2003-07-01 03:33:31 +0000292 # if home directory == root directory, this test makes no sense
293 if posixpath.expanduser("~") != '/':
294 self.assertEqual(
295 posixpath.expanduser("~") + "/",
296 posixpath.expanduser("~/")
297 )
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000298 self.assertEqual(
299 posixpath.expanduser(b"~") + b"/",
300 posixpath.expanduser(b"~/")
301 )
Ezio Melottie9615932010-01-24 19:26:24 +0000302 self.assertIsInstance(posixpath.expanduser("~root/"), str)
303 self.assertIsInstance(posixpath.expanduser("~foo/"), str)
304 self.assertIsInstance(posixpath.expanduser(b"~root/"), bytes)
305 self.assertIsInstance(posixpath.expanduser(b"~foo/"), bytes)
Brett Cannonb47243a2003-06-16 21:54:50 +0000306
Hirokazu Yamamoto71959632009-04-27 01:44:28 +0000307 with support.EnvironmentVarGuard() as env:
Walter Dörwald155374d2009-05-01 19:58:58 +0000308 env['HOME'] = '/'
Walter Dörwaldb525e182009-04-26 21:39:21 +0000309 self.assertEqual(posixpath.expanduser("~"), "/")
Jesus Cea7f0d8882012-05-10 05:10:50 +0200310 self.assertEqual(posixpath.expanduser("~/foo"), "/foo")
Michael Foord07926f02011-03-16 17:19:16 -0400311 # expanduser should fall back to using the password database
312 del env['HOME']
313 home = pwd.getpwuid(os.getuid()).pw_dir
314 self.assertEqual(posixpath.expanduser("~"), home)
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000315
Brett Cannonb47243a2003-06-16 21:54:50 +0000316 def test_normpath(self):
317 self.assertEqual(posixpath.normpath(""), ".")
318 self.assertEqual(posixpath.normpath("/"), "/")
319 self.assertEqual(posixpath.normpath("//"), "//")
320 self.assertEqual(posixpath.normpath("///"), "/")
321 self.assertEqual(posixpath.normpath("///foo/.//bar//"), "/foo/bar")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000322 self.assertEqual(posixpath.normpath("///foo/.//bar//.//..//.//baz"),
323 "/foo/baz")
Brett Cannonb47243a2003-06-16 21:54:50 +0000324 self.assertEqual(posixpath.normpath("///..//./foo/.//bar"), "/foo/bar")
325
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000326 self.assertEqual(posixpath.normpath(b""), b".")
327 self.assertEqual(posixpath.normpath(b"/"), b"/")
328 self.assertEqual(posixpath.normpath(b"//"), b"//")
329 self.assertEqual(posixpath.normpath(b"///"), b"/")
330 self.assertEqual(posixpath.normpath(b"///foo/.//bar//"), b"/foo/bar")
331 self.assertEqual(posixpath.normpath(b"///foo/.//bar//.//..//.//baz"),
332 b"/foo/baz")
333 self.assertEqual(posixpath.normpath(b"///..//./foo/.//bar"),
334 b"/foo/bar")
335
Brian Curtin52173d42010-12-02 18:29:18 +0000336 @unittest.skipUnless(hasattr(os, "symlink"),
337 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000338 @skip_if_ABSTFN_contains_backslash
339 def test_realpath_basic(self):
340 # Basic operation.
341 try:
342 os.symlink(ABSTFN+"1", ABSTFN)
343 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
344 finally:
345 support.unlink(ABSTFN)
Tim Petersa45cacf2004-08-20 03:47:14 +0000346
Brian Curtin52173d42010-12-02 18:29:18 +0000347 @unittest.skipUnless(hasattr(os, "symlink"),
348 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000349 @skip_if_ABSTFN_contains_backslash
Michael Foord07926f02011-03-16 17:19:16 -0400350 def test_realpath_relative(self):
351 try:
352 os.symlink(posixpath.relpath(ABSTFN+"1"), ABSTFN)
353 self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
354 finally:
355 support.unlink(ABSTFN)
356
357 @unittest.skipUnless(hasattr(os, "symlink"),
358 "Missing symlink implementation")
359 @skip_if_ABSTFN_contains_backslash
Brian Curtind40e6f72010-07-08 21:39:08 +0000360 def test_realpath_symlink_loops(self):
361 # Bug #930024, return the path unchanged if we get into an infinite
362 # symlink loop.
363 try:
364 old_path = abspath('.')
365 os.symlink(ABSTFN, ABSTFN)
366 self.assertEqual(realpath(ABSTFN), ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000367
Brian Curtind40e6f72010-07-08 21:39:08 +0000368 os.symlink(ABSTFN+"1", ABSTFN+"2")
369 os.symlink(ABSTFN+"2", ABSTFN+"1")
370 self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1")
371 self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000372
Brian Curtind40e6f72010-07-08 21:39:08 +0000373 # Test using relative path as well.
374 os.chdir(dirname(ABSTFN))
375 self.assertEqual(realpath(basename(ABSTFN)), ABSTFN)
376 finally:
377 os.chdir(old_path)
378 support.unlink(ABSTFN)
379 support.unlink(ABSTFN+"1")
380 support.unlink(ABSTFN+"2")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000381
Brian Curtin52173d42010-12-02 18:29:18 +0000382 @unittest.skipUnless(hasattr(os, "symlink"),
383 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000384 @skip_if_ABSTFN_contains_backslash
385 def test_realpath_resolve_parents(self):
386 # We also need to resolve any symlinks in the parents of a relative
387 # path passed to realpath. E.g.: current working directory is
388 # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call
389 # realpath("a"). This should return /usr/share/doc/a/.
390 try:
391 old_path = abspath('.')
392 os.mkdir(ABSTFN)
393 os.mkdir(ABSTFN + "/y")
394 os.symlink(ABSTFN + "/y", ABSTFN + "/k")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000395
Brian Curtind40e6f72010-07-08 21:39:08 +0000396 os.chdir(ABSTFN + "/k")
397 self.assertEqual(realpath("a"), ABSTFN + "/y/a")
398 finally:
399 os.chdir(old_path)
400 support.unlink(ABSTFN + "/k")
401 safe_rmdir(ABSTFN + "/y")
402 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000403
Brian Curtin52173d42010-12-02 18:29:18 +0000404 @unittest.skipUnless(hasattr(os, "symlink"),
405 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000406 @skip_if_ABSTFN_contains_backslash
407 def test_realpath_resolve_before_normalizing(self):
408 # Bug #990669: Symbolic links should be resolved before we
409 # normalize the path. E.g.: if we have directories 'a', 'k' and 'y'
410 # in the following hierarchy:
411 # a/k/y
412 #
413 # and a symbolic link 'link-y' pointing to 'y' in directory 'a',
414 # then realpath("link-y/..") should return 'k', not 'a'.
415 try:
416 old_path = abspath('.')
417 os.mkdir(ABSTFN)
418 os.mkdir(ABSTFN + "/k")
419 os.mkdir(ABSTFN + "/k/y")
420 os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y")
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000421
Brian Curtind40e6f72010-07-08 21:39:08 +0000422 # Absolute path.
423 self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k")
424 # Relative path.
425 os.chdir(dirname(ABSTFN))
426 self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."),
427 ABSTFN + "/k")
428 finally:
429 os.chdir(old_path)
430 support.unlink(ABSTFN + "/link-y")
431 safe_rmdir(ABSTFN + "/k/y")
432 safe_rmdir(ABSTFN + "/k")
433 safe_rmdir(ABSTFN)
Tim Peters5d36a552005-06-03 22:40:27 +0000434
Brian Curtin52173d42010-12-02 18:29:18 +0000435 @unittest.skipUnless(hasattr(os, "symlink"),
436 "Missing symlink implementation")
Brian Curtind40e6f72010-07-08 21:39:08 +0000437 @skip_if_ABSTFN_contains_backslash
438 def test_realpath_resolve_first(self):
439 # Bug #1213894: The first component of the path, if not absolute,
440 # must be resolved too.
Georg Brandl268e61c2005-06-03 14:28:50 +0000441
Brian Curtind40e6f72010-07-08 21:39:08 +0000442 try:
443 old_path = abspath('.')
444 os.mkdir(ABSTFN)
445 os.mkdir(ABSTFN + "/k")
446 os.symlink(ABSTFN, ABSTFN + "link")
447 os.chdir(dirname(ABSTFN))
Tim Peters5d36a552005-06-03 22:40:27 +0000448
Brian Curtind40e6f72010-07-08 21:39:08 +0000449 base = basename(ABSTFN)
450 self.assertEqual(realpath(base + "link"), ABSTFN)
451 self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k")
452 finally:
453 os.chdir(old_path)
454 support.unlink(ABSTFN + "link")
455 safe_rmdir(ABSTFN + "/k")
456 safe_rmdir(ABSTFN)
Johannes Gijsbers4ec40642004-08-14 15:01:53 +0000457
Guido van Rossumd8faa362007-04-27 19:54:29 +0000458 def test_relpath(self):
459 (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar")
460 try:
461 curdir = os.path.split(os.getcwd())[-1]
462 self.assertRaises(ValueError, posixpath.relpath, "")
463 self.assertEqual(posixpath.relpath("a"), "a")
464 self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a")
465 self.assertEqual(posixpath.relpath("a/b"), "a/b")
466 self.assertEqual(posixpath.relpath("../a/b"), "../a/b")
467 self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a")
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000468 self.assertEqual(posixpath.relpath("a/b", "../c"),
469 "../"+curdir+"/a/b")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000470 self.assertEqual(posixpath.relpath("a", "b/c"), "../../a")
Christian Heimesfaf2f632008-01-06 16:59:19 +0000471 self.assertEqual(posixpath.relpath("a", "a"), ".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000472 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x/y/z"), '../../../foo/bar/bat')
473 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/foo/bar"), 'bat')
474 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/"), 'foo/bar/bat')
475 self.assertEqual(posixpath.relpath("/", "/foo/bar/bat"), '../../..')
476 self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x"), '../foo/bar/bat')
477 self.assertEqual(posixpath.relpath("/x", "/foo/bar/bat"), '../../../x')
478 self.assertEqual(posixpath.relpath("/", "/"), '.')
479 self.assertEqual(posixpath.relpath("/a", "/a"), '.')
480 self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000481 finally:
482 os.getcwd = real_getcwd
Brett Cannonb47243a2003-06-16 21:54:50 +0000483
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000484 def test_relpath_bytes(self):
485 (real_getcwdb, os.getcwdb) = (os.getcwdb, lambda: br"/home/user/bar")
486 try:
487 curdir = os.path.split(os.getcwdb())[-1]
488 self.assertRaises(ValueError, posixpath.relpath, b"")
489 self.assertEqual(posixpath.relpath(b"a"), b"a")
490 self.assertEqual(posixpath.relpath(posixpath.abspath(b"a")), b"a")
491 self.assertEqual(posixpath.relpath(b"a/b"), b"a/b")
492 self.assertEqual(posixpath.relpath(b"../a/b"), b"../a/b")
493 self.assertEqual(posixpath.relpath(b"a", b"../b"),
494 b"../"+curdir+b"/a")
495 self.assertEqual(posixpath.relpath(b"a/b", b"../c"),
496 b"../"+curdir+b"/a/b")
497 self.assertEqual(posixpath.relpath(b"a", b"b/c"), b"../../a")
498 self.assertEqual(posixpath.relpath(b"a", b"a"), b".")
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000499 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x/y/z"), b'../../../foo/bar/bat')
500 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/foo/bar"), b'bat')
501 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/"), b'foo/bar/bat')
502 self.assertEqual(posixpath.relpath(b"/", b"/foo/bar/bat"), b'../../..')
503 self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x"), b'../foo/bar/bat')
504 self.assertEqual(posixpath.relpath(b"/x", b"/foo/bar/bat"), b'../../../x')
505 self.assertEqual(posixpath.relpath(b"/", b"/"), b'.')
506 self.assertEqual(posixpath.relpath(b"/a", b"/a"), b'.')
507 self.assertEqual(posixpath.relpath(b"/a/b", b"/a/b"), b'.')
Guido van Rossumf0af3e32008-10-02 18:55:37 +0000508
509 self.assertRaises(TypeError, posixpath.relpath, b"bytes", "str")
510 self.assertRaises(TypeError, posixpath.relpath, "str", b"bytes")
511 finally:
512 os.getcwdb = real_getcwdb
513
Michael Foord07926f02011-03-16 17:19:16 -0400514 def test_sameopenfile(self):
515 fname = support.TESTFN + "1"
516 with open(fname, "wb") as a, open(fname, "wb") as b:
517 self.assertTrue(posixpath.sameopenfile(a.fileno(), b.fileno()))
518
Florent Xiclunac9c79782010-03-08 12:24:53 +0000519
520class PosixCommonTest(test_genericpath.CommonTest):
521 pathmodule = posixpath
522 attributes = ['relpath', 'samefile', 'sameopenfile', 'samestat']
523
524
Brett Cannonb47243a2003-06-16 21:54:50 +0000525def test_main():
Florent Xiclunac9c79782010-03-08 12:24:53 +0000526 support.run_unittest(PosixPathTest, PosixCommonTest)
527
Brett Cannonb47243a2003-06-16 21:54:50 +0000528
529if __name__=="__main__":
530 test_main()