blob: 285fb69dc1e88f51a99657b67054580c92570a86 [file] [log] [blame]
Guido van Rossumead9d8d1999-02-03 17:21:21 +00001import ntpath
Mark Hammond673c6cf2000-08-14 06:21:26 +00002import os
Brian Curtin13a0db52010-09-06 19:46:17 +00003import sys
Victor Stinner1ab6c2d2011-11-15 22:27:41 +01004import unittest
5import warnings
Serhiy Storchakab21d1552018-03-02 11:53:51 +02006from test.support import TestFailed, FakePath
Florent Xiclunac9c79782010-03-08 12:24:53 +00007from test import support, test_genericpath
Brian Curtin62857742010-09-06 17:07:27 +00008from tempfile import TemporaryFile
Guido van Rossumead9d8d1999-02-03 17:21:21 +00009
Steve Dower75e06492019-08-21 13:43:06 -070010
Steve Dower23ad6d02018-02-22 10:39:10 -080011try:
12 import nt
13except ImportError:
14 # Most tests can complete without the nt module,
15 # but for those that require it we import here.
16 nt = None
Guido van Rossumead9d8d1999-02-03 17:21:21 +000017
Steve Dower75e06492019-08-21 13:43:06 -070018try:
19 ntpath._getfinalpathname
20except AttributeError:
21 HAVE_GETFINALPATHNAME = False
22else:
23 HAVE_GETFINALPATHNAME = True
24
25
Guido van Rossumead9d8d1999-02-03 17:21:21 +000026def tester(fn, wantResult):
Eric S. Raymondfc170b12001-02-09 11:51:27 +000027 fn = fn.replace("\\", "\\\\")
Fred Drake004d5e62000-10-23 17:22:08 +000028 gotResult = eval(fn)
29 if wantResult != gotResult:
Christian Heimesf6cd9672008-03-26 13:45:42 +000030 raise TestFailed("%s should return: %s but returned: %s" \
31 %(str(fn), str(wantResult), str(gotResult)))
Tim Peters6578dc92002-12-24 18:31:27 +000032
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +000033 # then with bytes
34 fn = fn.replace("('", "(b'")
35 fn = fn.replace('("', '(b"')
36 fn = fn.replace("['", "[b'")
37 fn = fn.replace('["', '[b"')
38 fn = fn.replace(", '", ", b'")
39 fn = fn.replace(', "', ', b"')
Serhiy Storchakadbb10192014-02-13 10:13:53 +020040 fn = os.fsencode(fn).decode('latin1')
41 fn = fn.encode('ascii', 'backslashreplace').decode('ascii')
Victor Stinner1ab6c2d2011-11-15 22:27:41 +010042 with warnings.catch_warnings():
43 warnings.simplefilter("ignore", DeprecationWarning)
44 gotResult = eval(fn)
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +000045 if isinstance(wantResult, str):
Serhiy Storchakadbb10192014-02-13 10:13:53 +020046 wantResult = os.fsencode(wantResult)
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +000047 elif isinstance(wantResult, tuple):
Serhiy Storchakadbb10192014-02-13 10:13:53 +020048 wantResult = tuple(os.fsencode(r) for r in wantResult)
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +000049 if wantResult != gotResult:
50 raise TestFailed("%s should return: %s but returned: %s" \
51 %(str(fn), str(wantResult), repr(gotResult)))
Guido van Rossumead9d8d1999-02-03 17:21:21 +000052
Mark Hammond5a607a32009-05-06 08:04:54 +000053
Christian Heimesf6cd9672008-03-26 13:45:42 +000054class TestNtpath(unittest.TestCase):
55 def test_splitext(self):
56 tester('ntpath.splitext("foo.ext")', ('foo', '.ext'))
57 tester('ntpath.splitext("/foo/foo.ext")', ('/foo/foo', '.ext'))
58 tester('ntpath.splitext(".ext")', ('.ext', ''))
59 tester('ntpath.splitext("\\foo.ext\\foo")', ('\\foo.ext\\foo', ''))
60 tester('ntpath.splitext("foo.ext\\")', ('foo.ext\\', ''))
61 tester('ntpath.splitext("")', ('', ''))
62 tester('ntpath.splitext("foo.bar.ext")', ('foo.bar', '.ext'))
63 tester('ntpath.splitext("xx/foo.bar.ext")', ('xx/foo.bar', '.ext'))
64 tester('ntpath.splitext("xx\\foo.bar.ext")', ('xx\\foo.bar', '.ext'))
65 tester('ntpath.splitext("c:a/b\\c.d")', ('c:a/b\\c', '.d'))
Guido van Rossumead9d8d1999-02-03 17:21:21 +000066
Christian Heimesf6cd9672008-03-26 13:45:42 +000067 def test_splitdrive(self):
68 tester('ntpath.splitdrive("c:\\foo\\bar")',
69 ('c:', '\\foo\\bar'))
70 tester('ntpath.splitdrive("c:/foo/bar")',
71 ('c:', '/foo/bar'))
Mark Hammond5a607a32009-05-06 08:04:54 +000072 tester('ntpath.splitdrive("\\\\conky\\mountpoint\\foo\\bar")',
Christian Heimesf6cd9672008-03-26 13:45:42 +000073 ('\\\\conky\\mountpoint', '\\foo\\bar'))
Mark Hammond5a607a32009-05-06 08:04:54 +000074 tester('ntpath.splitdrive("//conky/mountpoint/foo/bar")',
Christian Heimesf6cd9672008-03-26 13:45:42 +000075 ('//conky/mountpoint', '/foo/bar'))
Mark Hammond5a607a32009-05-06 08:04:54 +000076 tester('ntpath.splitdrive("\\\\\\conky\\mountpoint\\foo\\bar")',
77 ('', '\\\\\\conky\\mountpoint\\foo\\bar'))
78 tester('ntpath.splitdrive("///conky/mountpoint/foo/bar")',
79 ('', '///conky/mountpoint/foo/bar'))
80 tester('ntpath.splitdrive("\\\\conky\\\\mountpoint\\foo\\bar")',
81 ('', '\\\\conky\\\\mountpoint\\foo\\bar'))
82 tester('ntpath.splitdrive("//conky//mountpoint/foo/bar")',
83 ('', '//conky//mountpoint/foo/bar'))
Serhiy Storchaka3d7e1152013-12-16 14:34:55 +020084 # Issue #19911: UNC part containing U+0130
85 self.assertEqual(ntpath.splitdrive('//conky/MOUNTPOİNT/foo/bar'),
86 ('//conky/MOUNTPOİNT', '/foo/bar'))
Guido van Rossumead9d8d1999-02-03 17:21:21 +000087
Christian Heimesf6cd9672008-03-26 13:45:42 +000088 def test_split(self):
89 tester('ntpath.split("c:\\foo\\bar")', ('c:\\foo', 'bar'))
90 tester('ntpath.split("\\\\conky\\mountpoint\\foo\\bar")',
91 ('\\\\conky\\mountpoint\\foo', 'bar'))
Guido van Rossumead9d8d1999-02-03 17:21:21 +000092
Christian Heimesf6cd9672008-03-26 13:45:42 +000093 tester('ntpath.split("c:\\")', ('c:\\', ''))
94 tester('ntpath.split("\\\\conky\\mountpoint\\")',
Mark Hammond5a607a32009-05-06 08:04:54 +000095 ('\\\\conky\\mountpoint\\', ''))
Guido van Rossumead9d8d1999-02-03 17:21:21 +000096
Christian Heimesf6cd9672008-03-26 13:45:42 +000097 tester('ntpath.split("c:/")', ('c:/', ''))
Mark Hammond5a607a32009-05-06 08:04:54 +000098 tester('ntpath.split("//conky/mountpoint/")', ('//conky/mountpoint/', ''))
Mark Hammond673c6cf2000-08-14 06:21:26 +000099
Christian Heimesf6cd9672008-03-26 13:45:42 +0000100 def test_isabs(self):
101 tester('ntpath.isabs("c:\\")', 1)
102 tester('ntpath.isabs("\\\\conky\\mountpoint\\")', 1)
103 tester('ntpath.isabs("\\foo")', 1)
104 tester('ntpath.isabs("\\foo\\bar")', 1)
Tim Petersd4f7f602001-07-19 19:11:41 +0000105
Christian Heimesf6cd9672008-03-26 13:45:42 +0000106 def test_commonprefix(self):
107 tester('ntpath.commonprefix(["/home/swenson/spam", "/home/swen/spam"])',
108 "/home/swen")
109 tester('ntpath.commonprefix(["\\home\\swen\\spam", "\\home\\swen\\eggs"])',
110 "\\home\\swen\\")
111 tester('ntpath.commonprefix(["/home/swen/spam", "/home/swen/spam"])',
112 "/home/swen/spam")
Tim Peters6a3e5f12001-11-05 21:25:02 +0000113
Christian Heimesf6cd9672008-03-26 13:45:42 +0000114 def test_join(self):
115 tester('ntpath.join("")', '')
116 tester('ntpath.join("", "", "")', '')
117 tester('ntpath.join("a")', 'a')
118 tester('ntpath.join("/a")', '/a')
119 tester('ntpath.join("\\a")', '\\a')
120 tester('ntpath.join("a:")', 'a:')
Christian Heimesf6cd9672008-03-26 13:45:42 +0000121 tester('ntpath.join("a:", "\\b")', 'a:\\b')
Christian Heimesf6cd9672008-03-26 13:45:42 +0000122 tester('ntpath.join("a", "\\b")', '\\b')
123 tester('ntpath.join("a", "b", "c")', 'a\\b\\c')
124 tester('ntpath.join("a\\", "b", "c")', 'a\\b\\c')
125 tester('ntpath.join("a", "b\\", "c")', 'a\\b\\c')
126 tester('ntpath.join("a", "b", "\\c")', '\\c')
127 tester('ntpath.join("d:\\", "\\pleep")', 'd:\\pleep')
128 tester('ntpath.join("d:\\", "a", "b")', 'd:\\a\\b')
Tim Peters54a14a32001-08-30 22:05:26 +0000129
Christian Heimesf6cd9672008-03-26 13:45:42 +0000130 tester("ntpath.join('', 'a')", 'a')
131 tester("ntpath.join('', '', '', '', 'a')", 'a')
132 tester("ntpath.join('a', '')", 'a\\')
133 tester("ntpath.join('a', '', '', '', '')", 'a\\')
134 tester("ntpath.join('a\\', '')", 'a\\')
135 tester("ntpath.join('a\\', '', '', '', '')", 'a\\')
Serhiy Storchakac369c2c2014-01-27 23:15:14 +0200136 tester("ntpath.join('a/', '')", 'a/')
Tim Peters54a14a32001-08-30 22:05:26 +0000137
Serhiy Storchakac369c2c2014-01-27 23:15:14 +0200138 tester("ntpath.join('a/b', 'x/y')", 'a/b\\x/y')
139 tester("ntpath.join('/a/b', 'x/y')", '/a/b\\x/y')
140 tester("ntpath.join('/a/b/', 'x/y')", '/a/b/x/y')
141 tester("ntpath.join('c:', 'x/y')", 'c:x/y')
142 tester("ntpath.join('c:a/b', 'x/y')", 'c:a/b\\x/y')
143 tester("ntpath.join('c:a/b/', 'x/y')", 'c:a/b/x/y')
144 tester("ntpath.join('c:/', 'x/y')", 'c:/x/y')
145 tester("ntpath.join('c:/a/b', 'x/y')", 'c:/a/b\\x/y')
146 tester("ntpath.join('c:/a/b/', 'x/y')", 'c:/a/b/x/y')
147 tester("ntpath.join('//computer/share', 'x/y')", '//computer/share\\x/y')
148 tester("ntpath.join('//computer/share/', 'x/y')", '//computer/share/x/y')
149 tester("ntpath.join('//computer/share/a/b', 'x/y')", '//computer/share/a/b\\x/y')
Mark Hammond5a607a32009-05-06 08:04:54 +0000150
Serhiy Storchakac369c2c2014-01-27 23:15:14 +0200151 tester("ntpath.join('a/b', '/x/y')", '/x/y')
152 tester("ntpath.join('/a/b', '/x/y')", '/x/y')
153 tester("ntpath.join('c:', '/x/y')", 'c:/x/y')
154 tester("ntpath.join('c:a/b', '/x/y')", 'c:/x/y')
155 tester("ntpath.join('c:/', '/x/y')", 'c:/x/y')
156 tester("ntpath.join('c:/a/b', '/x/y')", 'c:/x/y')
157 tester("ntpath.join('//computer/share', '/x/y')", '//computer/share/x/y')
158 tester("ntpath.join('//computer/share/', '/x/y')", '//computer/share/x/y')
159 tester("ntpath.join('//computer/share/a', '/x/y')", '//computer/share/x/y')
160
161 tester("ntpath.join('c:', 'C:x/y')", 'C:x/y')
162 tester("ntpath.join('c:a/b', 'C:x/y')", 'C:a/b\\x/y')
163 tester("ntpath.join('c:/', 'C:x/y')", 'C:/x/y')
164 tester("ntpath.join('c:/a/b', 'C:x/y')", 'C:/a/b\\x/y')
165
166 for x in ('', 'a/b', '/a/b', 'c:', 'c:a/b', 'c:/', 'c:/a/b',
167 '//computer/share', '//computer/share/', '//computer/share/a/b'):
168 for y in ('d:', 'd:x/y', 'd:/', 'd:/x/y',
169 '//machine/common', '//machine/common/', '//machine/common/x/y'):
170 tester("ntpath.join(%r, %r)" % (x, y), y)
Mark Hammond5a607a32009-05-06 08:04:54 +0000171
172 tester("ntpath.join('\\\\computer\\share\\', 'a', 'b')", '\\\\computer\\share\\a\\b')
173 tester("ntpath.join('\\\\computer\\share', 'a', 'b')", '\\\\computer\\share\\a\\b')
174 tester("ntpath.join('\\\\computer\\share', 'a\\b')", '\\\\computer\\share\\a\\b')
175 tester("ntpath.join('//computer/share/', 'a', 'b')", '//computer/share/a\\b')
176 tester("ntpath.join('//computer/share', 'a', 'b')", '//computer/share\\a\\b')
177 tester("ntpath.join('//computer/share', 'a/b')", '//computer/share\\a/b')
178
Christian Heimesf6cd9672008-03-26 13:45:42 +0000179 def test_normpath(self):
180 tester("ntpath.normpath('A//////././//.//B')", r'A\B')
181 tester("ntpath.normpath('A/./B')", r'A\B')
182 tester("ntpath.normpath('A/foo/../B')", r'A\B')
183 tester("ntpath.normpath('C:A//B')", r'C:A\B')
184 tester("ntpath.normpath('D:A/./B')", r'D:A\B')
185 tester("ntpath.normpath('e:A/foo/../B')", r'e:A\B')
Tim Peters54a14a32001-08-30 22:05:26 +0000186
Christian Heimesf6cd9672008-03-26 13:45:42 +0000187 tester("ntpath.normpath('C:///A//B')", r'C:\A\B')
188 tester("ntpath.normpath('D:///A/./B')", r'D:\A\B')
189 tester("ntpath.normpath('e:///A/foo/../B')", r'e:\A\B')
Thomas Woutersb2137042007-02-01 18:02:27 +0000190
Christian Heimesf6cd9672008-03-26 13:45:42 +0000191 tester("ntpath.normpath('..')", r'..')
192 tester("ntpath.normpath('.')", r'.')
193 tester("ntpath.normpath('')", r'.')
194 tester("ntpath.normpath('/')", '\\')
195 tester("ntpath.normpath('c:/')", 'c:\\')
196 tester("ntpath.normpath('/../.././..')", '\\')
197 tester("ntpath.normpath('c:/../../..')", 'c:\\')
198 tester("ntpath.normpath('../.././..')", r'..\..\..')
199 tester("ntpath.normpath('K:../.././..')", r'K:..\..\..')
200 tester("ntpath.normpath('C:////a/b')", r'C:\a\b')
201 tester("ntpath.normpath('//machine/share//a/b')", r'\\machine\share\a\b')
Fred Drake5e997312002-01-15 03:46:43 +0000202
Georg Brandlcfb68212010-07-31 21:40:15 +0000203 tester("ntpath.normpath('\\\\.\\NUL')", r'\\.\NUL')
204 tester("ntpath.normpath('\\\\?\\D:/XY\\Z')", r'\\?\D:/XY\Z')
205
Steve Dower75e06492019-08-21 13:43:06 -0700206 def test_realpath_curdir(self):
207 expected = ntpath.normpath(os.getcwd())
208 tester("ntpath.realpath('.')", expected)
209 tester("ntpath.realpath('./.')", expected)
210 tester("ntpath.realpath('/'.join(['.'] * 100))", expected)
211 tester("ntpath.realpath('.\\.')", expected)
212 tester("ntpath.realpath('\\'.join(['.'] * 100))", expected)
213
214 def test_realpath_pardir(self):
215 expected = ntpath.normpath(os.getcwd())
216 tester("ntpath.realpath('..')", ntpath.dirname(expected))
217 tester("ntpath.realpath('../..')",
218 ntpath.dirname(ntpath.dirname(expected)))
219 tester("ntpath.realpath('/'.join(['..'] * 50))",
220 ntpath.splitdrive(expected)[0] + '\\')
221 tester("ntpath.realpath('..\\..')",
222 ntpath.dirname(ntpath.dirname(expected)))
223 tester("ntpath.realpath('\\'.join(['..'] * 50))",
224 ntpath.splitdrive(expected)[0] + '\\')
225
226 @support.skip_unless_symlink
227 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
228 def test_realpath_basic(self):
229 ABSTFN = ntpath.abspath(support.TESTFN)
230 open(ABSTFN, "wb").close()
231 self.addCleanup(support.unlink, ABSTFN)
232 self.addCleanup(support.unlink, ABSTFN + "1")
233
234 os.symlink(ABSTFN, ABSTFN + "1")
235 self.assertEqual(ntpath.realpath(ABSTFN + "1"), ABSTFN)
236 self.assertEqual(ntpath.realpath(os.fsencode(ABSTFN + "1")),
237 os.fsencode(ABSTFN))
238
239 @support.skip_unless_symlink
240 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
241 def test_realpath_relative(self):
242 ABSTFN = ntpath.abspath(support.TESTFN)
243 open(ABSTFN, "wb").close()
244 self.addCleanup(support.unlink, ABSTFN)
245 self.addCleanup(support.unlink, ABSTFN + "1")
246
247 os.symlink(ABSTFN, ntpath.relpath(ABSTFN + "1"))
248 self.assertEqual(ntpath.realpath(ABSTFN + "1"), ABSTFN)
249
250 @support.skip_unless_symlink
251 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
252 def test_realpath_broken_symlinks(self):
253 ABSTFN = ntpath.abspath(support.TESTFN)
254 os.mkdir(ABSTFN)
255 self.addCleanup(support.rmtree, ABSTFN)
256
257 with support.change_cwd(ABSTFN):
258 os.mkdir("subdir")
259 os.chdir("subdir")
260 os.symlink(".", "recursive")
261 os.symlink("..", "parent")
262 os.chdir("..")
263 os.symlink(".", "self")
264 os.symlink("missing", "broken")
265 os.symlink(r"broken\bar", "broken1")
266 os.symlink(r"self\self\broken", "broken2")
267 os.symlink(r"subdir\parent\subdir\parent\broken", "broken3")
268 os.symlink(ABSTFN + r"\broken", "broken4")
269 os.symlink(r"recursive\..\broken", "broken5")
270
271 self.assertEqual(ntpath.realpath("broken"),
272 ABSTFN + r"\missing")
273 self.assertEqual(ntpath.realpath(r"broken\foo"),
274 ABSTFN + r"\missing\foo")
275 self.assertEqual(ntpath.realpath(r"broken1"),
276 ABSTFN + r"\missing\bar")
277 self.assertEqual(ntpath.realpath(r"broken1\baz"),
278 ABSTFN + r"\missing\bar\baz")
279 self.assertEqual(ntpath.realpath("broken2"),
280 ABSTFN + r"\missing")
281 self.assertEqual(ntpath.realpath("broken3"),
282 ABSTFN + r"\missing")
283 self.assertEqual(ntpath.realpath("broken4"),
284 ABSTFN + r"\missing")
285 self.assertEqual(ntpath.realpath("broken5"),
286 ABSTFN + r"\missing")
287
288 self.assertEqual(ntpath.realpath(b"broken"),
289 os.fsencode(ABSTFN + r"\missing"))
290 self.assertEqual(ntpath.realpath(rb"broken\foo"),
291 os.fsencode(ABSTFN + r"\missing\foo"))
292 self.assertEqual(ntpath.realpath(rb"broken1"),
293 os.fsencode(ABSTFN + r"\missing\bar"))
294 self.assertEqual(ntpath.realpath(rb"broken1\baz"),
295 os.fsencode(ABSTFN + r"\missing\bar\baz"))
296 self.assertEqual(ntpath.realpath(b"broken2"),
297 os.fsencode(ABSTFN + r"\missing"))
298 self.assertEqual(ntpath.realpath(rb"broken3"),
299 os.fsencode(ABSTFN + r"\missing"))
300 self.assertEqual(ntpath.realpath(b"broken4"),
301 os.fsencode(ABSTFN + r"\missing"))
302 self.assertEqual(ntpath.realpath(b"broken5"),
303 os.fsencode(ABSTFN + r"\missing"))
304
305 @support.skip_unless_symlink
306 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
307 def test_realpath_symlink_loops(self):
308 # Bug #930024, return the path unchanged if we get into an infinite
309 # symlink loop.
310 ABSTFN = ntpath.abspath(support.TESTFN)
311 self.addCleanup(support.unlink, ABSTFN)
312 self.addCleanup(support.unlink, ABSTFN + "1")
313 self.addCleanup(support.unlink, ABSTFN + "2")
314 self.addCleanup(support.unlink, ABSTFN + "y")
315 self.addCleanup(support.unlink, ABSTFN + "c")
316 self.addCleanup(support.unlink, ABSTFN + "a")
317
318 P = "\\\\?\\"
319
320 os.symlink(ABSTFN, ABSTFN)
321 self.assertEqual(ntpath.realpath(ABSTFN), P + ABSTFN)
322
323 # cycles are non-deterministic as to which path is returned, but
324 # it will always be the fully resolved path of one member of the cycle
325 os.symlink(ABSTFN + "1", ABSTFN + "2")
326 os.symlink(ABSTFN + "2", ABSTFN + "1")
327 expected = (P + ABSTFN + "1", P + ABSTFN + "2")
328 self.assertIn(ntpath.realpath(ABSTFN + "1"), expected)
329 self.assertIn(ntpath.realpath(ABSTFN + "2"), expected)
330
331 self.assertIn(ntpath.realpath(ABSTFN + "1\\x"),
332 (ntpath.join(r, "x") for r in expected))
333 self.assertEqual(ntpath.realpath(ABSTFN + "1\\.."),
334 ntpath.dirname(ABSTFN))
335 self.assertEqual(ntpath.realpath(ABSTFN + "1\\..\\x"),
Steve Dower06be2c72019-08-21 16:45:02 -0700336 ntpath.dirname(ABSTFN) + "\\x")
Steve Dower75e06492019-08-21 13:43:06 -0700337 os.symlink(ABSTFN + "x", ABSTFN + "y")
338 self.assertEqual(ntpath.realpath(ABSTFN + "1\\..\\"
339 + ntpath.basename(ABSTFN) + "y"),
Steve Dower06be2c72019-08-21 16:45:02 -0700340 ABSTFN + "x")
Steve Dower75e06492019-08-21 13:43:06 -0700341 self.assertIn(ntpath.realpath(ABSTFN + "1\\..\\"
342 + ntpath.basename(ABSTFN) + "1"),
343 expected)
344
345 os.symlink(ntpath.basename(ABSTFN) + "a\\b", ABSTFN + "a")
346 self.assertEqual(ntpath.realpath(ABSTFN + "a"), P + ABSTFN + "a")
347
348 os.symlink("..\\" + ntpath.basename(ntpath.dirname(ABSTFN))
349 + "\\" + ntpath.basename(ABSTFN) + "c", ABSTFN + "c")
350 self.assertEqual(ntpath.realpath(ABSTFN + "c"), P + ABSTFN + "c")
351
352 # Test using relative path as well.
353 self.assertEqual(ntpath.realpath(ntpath.basename(ABSTFN)), P + ABSTFN)
354
355 @support.skip_unless_symlink
356 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
357 def test_realpath_symlink_prefix(self):
358 ABSTFN = ntpath.abspath(support.TESTFN)
359 self.addCleanup(support.unlink, ABSTFN + "3")
360 self.addCleanup(support.unlink, "\\\\?\\" + ABSTFN + "3.")
361 self.addCleanup(support.unlink, ABSTFN + "3link")
362 self.addCleanup(support.unlink, ABSTFN + "3.link")
363
364 with open(ABSTFN + "3", "wb") as f:
365 f.write(b'0')
366 os.symlink(ABSTFN + "3", ABSTFN + "3link")
367
368 with open("\\\\?\\" + ABSTFN + "3.", "wb") as f:
369 f.write(b'1')
370 os.symlink("\\\\?\\" + ABSTFN + "3.", ABSTFN + "3.link")
371
372 self.assertEqual(ntpath.realpath(ABSTFN + "3link"),
373 ABSTFN + "3")
374 self.assertEqual(ntpath.realpath(ABSTFN + "3.link"),
375 "\\\\?\\" + ABSTFN + "3.")
376
377 # Resolved paths should be usable to open target files
378 with open(ntpath.realpath(ABSTFN + "3link"), "rb") as f:
379 self.assertEqual(f.read(), b'0')
380 with open(ntpath.realpath(ABSTFN + "3.link"), "rb") as f:
381 self.assertEqual(f.read(), b'1')
382
383 # When the prefix is included, it is not stripped
384 self.assertEqual(ntpath.realpath("\\\\?\\" + ABSTFN + "3link"),
385 "\\\\?\\" + ABSTFN + "3")
386 self.assertEqual(ntpath.realpath("\\\\?\\" + ABSTFN + "3.link"),
387 "\\\\?\\" + ABSTFN + "3.")
388
Christian Heimesf6cd9672008-03-26 13:45:42 +0000389 def test_expandvars(self):
Walter Dörwald155374d2009-05-01 19:58:58 +0000390 with support.EnvironmentVarGuard() as env:
391 env.clear()
392 env["foo"] = "bar"
393 env["{foo"] = "baz1"
394 env["{foo}"] = "baz2"
Christian Heimesf6cd9672008-03-26 13:45:42 +0000395 tester('ntpath.expandvars("foo")', "foo")
396 tester('ntpath.expandvars("$foo bar")', "bar bar")
397 tester('ntpath.expandvars("${foo}bar")', "barbar")
398 tester('ntpath.expandvars("$[foo]bar")', "$[foo]bar")
399 tester('ntpath.expandvars("$bar bar")', "$bar bar")
400 tester('ntpath.expandvars("$?bar")', "$?bar")
Christian Heimesf6cd9672008-03-26 13:45:42 +0000401 tester('ntpath.expandvars("$foo}bar")', "bar}bar")
402 tester('ntpath.expandvars("${foo")', "${foo")
403 tester('ntpath.expandvars("${{foo}}")', "baz1}")
404 tester('ntpath.expandvars("$foo$foo")', "barbar")
405 tester('ntpath.expandvars("$bar$bar")', "$bar$bar")
406 tester('ntpath.expandvars("%foo% bar")', "bar bar")
407 tester('ntpath.expandvars("%foo%bar")', "barbar")
408 tester('ntpath.expandvars("%foo%%foo%")', "barbar")
409 tester('ntpath.expandvars("%%foo%%foo%foo%")', "%foo%foobar")
410 tester('ntpath.expandvars("%?bar%")', "%?bar%")
411 tester('ntpath.expandvars("%foo%%bar")', "bar%bar")
412 tester('ntpath.expandvars("\'%foo%\'%bar")', "\'%foo%\'%bar")
Serhiy Storchaka1b87ae02015-03-25 16:40:15 +0200413 tester('ntpath.expandvars("bar\'%foo%")', "bar\'%foo%")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000414
Serhiy Storchakadbb10192014-02-13 10:13:53 +0200415 @unittest.skipUnless(support.FS_NONASCII, 'need support.FS_NONASCII')
416 def test_expandvars_nonascii(self):
417 def check(value, expected):
418 tester('ntpath.expandvars(%r)' % value, expected)
419 with support.EnvironmentVarGuard() as env:
420 env.clear()
421 nonascii = support.FS_NONASCII
422 env['spam'] = nonascii
423 env[nonascii] = 'ham' + nonascii
424 check('$spam bar', '%s bar' % nonascii)
425 check('$%s bar' % nonascii, '$%s bar' % nonascii)
426 check('${spam}bar', '%sbar' % nonascii)
427 check('${%s}bar' % nonascii, 'ham%sbar' % nonascii)
428 check('$spam}bar', '%s}bar' % nonascii)
429 check('$%s}bar' % nonascii, '$%s}bar' % nonascii)
430 check('%spam% bar', '%s bar' % nonascii)
431 check('%{}% bar'.format(nonascii), 'ham%s bar' % nonascii)
432 check('%spam%bar', '%sbar' % nonascii)
433 check('%{}%bar'.format(nonascii), 'ham%sbar' % nonascii)
434
Serhiy Storchakaffc1e6d2014-05-28 18:11:29 +0300435 def test_expanduser(self):
436 tester('ntpath.expanduser("test")', 'test')
437
438 with support.EnvironmentVarGuard() as env:
439 env.clear()
440 tester('ntpath.expanduser("~test")', '~test')
441
442 env['HOMEPATH'] = 'eric\\idle'
443 env['HOMEDRIVE'] = 'C:\\'
444 tester('ntpath.expanduser("~test")', 'C:\\eric\\test')
445 tester('ntpath.expanduser("~")', 'C:\\eric\\idle')
446
447 del env['HOMEDRIVE']
448 tester('ntpath.expanduser("~test")', 'eric\\test')
449 tester('ntpath.expanduser("~")', 'eric\\idle')
450
451 env.clear()
452 env['USERPROFILE'] = 'C:\\eric\\idle'
453 tester('ntpath.expanduser("~test")', 'C:\\eric\\test')
454 tester('ntpath.expanduser("~")', 'C:\\eric\\idle')
Serhiy Storchakaffc1e6d2014-05-28 18:11:29 +0300455 tester('ntpath.expanduser("~test\\foo\\bar")',
Anthony Sottile25ec4a42019-03-12 08:39:57 -0700456 'C:\\eric\\test\\foo\\bar')
Serhiy Storchakaffc1e6d2014-05-28 18:11:29 +0300457 tester('ntpath.expanduser("~test/foo/bar")',
Anthony Sottile25ec4a42019-03-12 08:39:57 -0700458 'C:\\eric\\test/foo/bar')
Serhiy Storchakaffc1e6d2014-05-28 18:11:29 +0300459 tester('ntpath.expanduser("~\\foo\\bar")',
Anthony Sottile25ec4a42019-03-12 08:39:57 -0700460 'C:\\eric\\idle\\foo\\bar')
Serhiy Storchakaffc1e6d2014-05-28 18:11:29 +0300461 tester('ntpath.expanduser("~/foo/bar")',
Anthony Sottile25ec4a42019-03-12 08:39:57 -0700462 'C:\\eric\\idle/foo/bar')
463
464 # bpo-36264: ignore `HOME` when set on windows
465 env.clear()
466 env['HOME'] = 'F:\\'
467 env['USERPROFILE'] = 'C:\\eric\\idle'
468 tester('ntpath.expanduser("~test")', 'C:\\eric\\test')
469 tester('ntpath.expanduser("~")', 'C:\\eric\\idle')
Serhiy Storchakaffc1e6d2014-05-28 18:11:29 +0300470
Steve Dower23ad6d02018-02-22 10:39:10 -0800471 @unittest.skipUnless(nt, "abspath requires 'nt' module")
Christian Heimesf6cd9672008-03-26 13:45:42 +0000472 def test_abspath(self):
Steve Dower23ad6d02018-02-22 10:39:10 -0800473 tester('ntpath.abspath("C:\\")', "C:\\")
Franz Wöllertd2e902e2018-07-29 14:47:09 +0200474 with support.temp_cwd(support.TESTFN) as cwd_dir: # bpo-31047
475 tester('ntpath.abspath("")', cwd_dir)
476 tester('ntpath.abspath(" ")', cwd_dir + "\\ ")
477 tester('ntpath.abspath("?")', cwd_dir + "\\?")
Tim Grahamd03b7752018-10-25 11:26:38 -0400478 drive, _ = ntpath.splitdrive(cwd_dir)
479 tester('ntpath.abspath("/abc/")', drive + "\\abc")
Christian Heimesf6cd9672008-03-26 13:45:42 +0000480
481 def test_relpath(self):
Christian Heimesf6cd9672008-03-26 13:45:42 +0000482 tester('ntpath.relpath("a")', 'a')
Steve Dower75e06492019-08-21 13:43:06 -0700483 tester('ntpath.relpath(ntpath.abspath("a"))', 'a')
Christian Heimesf6cd9672008-03-26 13:45:42 +0000484 tester('ntpath.relpath("a/b")', 'a\\b')
485 tester('ntpath.relpath("../a/b")', '..\\a\\b')
Serhiy Storchaka5106d042015-01-26 10:26:14 +0200486 with support.temp_cwd(support.TESTFN) as cwd_dir:
Steve Dower75e06492019-08-21 13:43:06 -0700487 currentdir = ntpath.basename(cwd_dir)
Serhiy Storchaka5106d042015-01-26 10:26:14 +0200488 tester('ntpath.relpath("a", "../b")', '..\\'+currentdir+'\\a')
489 tester('ntpath.relpath("a/b", "../c")', '..\\'+currentdir+'\\a\\b')
Christian Heimesf6cd9672008-03-26 13:45:42 +0000490 tester('ntpath.relpath("a", "b/c")', '..\\..\\a')
Mark Hammond5a607a32009-05-06 08:04:54 +0000491 tester('ntpath.relpath("c:/foo/bar/bat", "c:/x/y")', '..\\..\\foo\\bar\\bat')
Christian Heimesf6cd9672008-03-26 13:45:42 +0000492 tester('ntpath.relpath("//conky/mountpoint/a", "//conky/mountpoint/b/c")', '..\\..\\a')
493 tester('ntpath.relpath("a", "a")', '.')
Mark Hammond5a607a32009-05-06 08:04:54 +0000494 tester('ntpath.relpath("/foo/bar/bat", "/x/y/z")', '..\\..\\..\\foo\\bar\\bat')
495 tester('ntpath.relpath("/foo/bar/bat", "/foo/bar")', 'bat')
496 tester('ntpath.relpath("/foo/bar/bat", "/")', 'foo\\bar\\bat')
497 tester('ntpath.relpath("/", "/foo/bar/bat")', '..\\..\\..')
498 tester('ntpath.relpath("/foo/bar/bat", "/x")', '..\\foo\\bar\\bat')
499 tester('ntpath.relpath("/x", "/foo/bar/bat")', '..\\..\\..\\x')
500 tester('ntpath.relpath("/", "/")', '.')
501 tester('ntpath.relpath("/a", "/a")', '.')
502 tester('ntpath.relpath("/a/b", "/a/b")', '.')
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000503 tester('ntpath.relpath("c:/foo", "C:/FOO")', '.')
Christian Heimesf6cd9672008-03-26 13:45:42 +0000504
Serhiy Storchaka38220932015-03-31 15:31:53 +0300505 def test_commonpath(self):
506 def check(paths, expected):
507 tester(('ntpath.commonpath(%r)' % paths).replace('\\\\', '\\'),
508 expected)
509 def check_error(exc, paths):
510 self.assertRaises(exc, ntpath.commonpath, paths)
511 self.assertRaises(exc, ntpath.commonpath,
512 [os.fsencode(p) for p in paths])
513
514 self.assertRaises(ValueError, ntpath.commonpath, [])
515 check_error(ValueError, ['C:\\Program Files', 'Program Files'])
516 check_error(ValueError, ['C:\\Program Files', 'C:Program Files'])
517 check_error(ValueError, ['\\Program Files', 'Program Files'])
518 check_error(ValueError, ['Program Files', 'C:\\Program Files'])
519 check(['C:\\Program Files'], 'C:\\Program Files')
520 check(['C:\\Program Files', 'C:\\Program Files'], 'C:\\Program Files')
521 check(['C:\\Program Files\\', 'C:\\Program Files'],
522 'C:\\Program Files')
523 check(['C:\\Program Files\\', 'C:\\Program Files\\'],
524 'C:\\Program Files')
525 check(['C:\\\\Program Files', 'C:\\Program Files\\\\'],
526 'C:\\Program Files')
527 check(['C:\\.\\Program Files', 'C:\\Program Files\\.'],
528 'C:\\Program Files')
529 check(['C:\\', 'C:\\bin'], 'C:\\')
530 check(['C:\\Program Files', 'C:\\bin'], 'C:\\')
531 check(['C:\\Program Files', 'C:\\Program Files\\Bar'],
532 'C:\\Program Files')
533 check(['C:\\Program Files\\Foo', 'C:\\Program Files\\Bar'],
534 'C:\\Program Files')
535 check(['C:\\Program Files', 'C:\\Projects'], 'C:\\')
536 check(['C:\\Program Files\\', 'C:\\Projects'], 'C:\\')
537
538 check(['C:\\Program Files\\Foo', 'C:/Program Files/Bar'],
539 'C:\\Program Files')
540 check(['C:\\Program Files\\Foo', 'c:/program files/bar'],
541 'C:\\Program Files')
542 check(['c:/program files/bar', 'C:\\Program Files\\Foo'],
543 'c:\\program files')
544
545 check_error(ValueError, ['C:\\Program Files', 'D:\\Program Files'])
546
547 check(['spam'], 'spam')
548 check(['spam', 'spam'], 'spam')
549 check(['spam', 'alot'], '')
550 check(['and\\jam', 'and\\spam'], 'and')
551 check(['and\\\\jam', 'and\\spam\\\\'], 'and')
552 check(['and\\.\\jam', '.\\and\\spam'], 'and')
553 check(['and\\jam', 'and\\spam', 'alot'], '')
554 check(['and\\jam', 'and\\spam', 'and'], 'and')
555 check(['C:and\\jam', 'C:and\\spam'], 'C:and')
556
557 check([''], '')
558 check(['', 'spam\\alot'], '')
559 check_error(ValueError, ['', '\\spam\\alot'])
560
561 self.assertRaises(TypeError, ntpath.commonpath,
562 [b'C:\\Program Files', 'C:\\Program Files\\Foo'])
563 self.assertRaises(TypeError, ntpath.commonpath,
564 [b'C:\\Program Files', 'Program Files\\Foo'])
565 self.assertRaises(TypeError, ntpath.commonpath,
566 [b'Program Files', 'C:\\Program Files\\Foo'])
567 self.assertRaises(TypeError, ntpath.commonpath,
568 ['C:\\Program Files', b'C:\\Program Files\\Foo'])
569 self.assertRaises(TypeError, ntpath.commonpath,
570 ['C:\\Program Files', b'Program Files\\Foo'])
571 self.assertRaises(TypeError, ntpath.commonpath,
572 ['Program Files', b'C:\\Program Files\\Foo'])
573
Brian Curtin62857742010-09-06 17:07:27 +0000574 def test_sameopenfile(self):
575 with TemporaryFile() as tf1, TemporaryFile() as tf2:
576 # Make sure the same file is really the same
577 self.assertTrue(ntpath.sameopenfile(tf1.fileno(), tf1.fileno()))
578 # Make sure different files are really different
579 self.assertFalse(ntpath.sameopenfile(tf1.fileno(), tf2.fileno()))
Brian Curtin13a0db52010-09-06 19:46:17 +0000580 # Make sure invalid values don't cause issues on win32
581 if sys.platform == "win32":
Hirokazu Yamamoto26253bb2010-12-05 04:16:47 +0000582 with self.assertRaises(OSError):
Brian Curtin13a0db52010-09-06 19:46:17 +0000583 # Invalid file descriptors shouldn't display assert
584 # dialogs (#4804)
585 ntpath.sameopenfile(-1, -1)
Brian Curtin62857742010-09-06 17:07:27 +0000586
Tim Golden6b528062013-08-01 12:44:00 +0100587 def test_ismount(self):
588 self.assertTrue(ntpath.ismount("c:\\"))
589 self.assertTrue(ntpath.ismount("C:\\"))
590 self.assertTrue(ntpath.ismount("c:/"))
591 self.assertTrue(ntpath.ismount("C:/"))
592 self.assertTrue(ntpath.ismount("\\\\.\\c:\\"))
593 self.assertTrue(ntpath.ismount("\\\\.\\C:\\"))
594
595 self.assertTrue(ntpath.ismount(b"c:\\"))
596 self.assertTrue(ntpath.ismount(b"C:\\"))
597 self.assertTrue(ntpath.ismount(b"c:/"))
598 self.assertTrue(ntpath.ismount(b"C:/"))
599 self.assertTrue(ntpath.ismount(b"\\\\.\\c:\\"))
600 self.assertTrue(ntpath.ismount(b"\\\\.\\C:\\"))
601
602 with support.temp_dir() as d:
603 self.assertFalse(ntpath.ismount(d))
604
Tim Goldenb2fcebb2013-08-01 13:58:58 +0100605 if sys.platform == "win32":
606 #
607 # Make sure the current folder isn't the root folder
608 # (or any other volume root). The drive-relative
609 # locations below cannot then refer to mount points
610 #
611 drive, path = ntpath.splitdrive(sys.executable)
Steve Dower75e06492019-08-21 13:43:06 -0700612 with support.change_cwd(ntpath.dirname(sys.executable)):
Tim Goldenb2fcebb2013-08-01 13:58:58 +0100613 self.assertFalse(ntpath.ismount(drive.lower()))
614 self.assertFalse(ntpath.ismount(drive.upper()))
Tim Golden6b528062013-08-01 12:44:00 +0100615
Tim Goldenb2fcebb2013-08-01 13:58:58 +0100616 self.assertTrue(ntpath.ismount("\\\\localhost\\c$"))
617 self.assertTrue(ntpath.ismount("\\\\localhost\\c$\\"))
Tim Golden6b528062013-08-01 12:44:00 +0100618
Tim Goldenb2fcebb2013-08-01 13:58:58 +0100619 self.assertTrue(ntpath.ismount(b"\\\\localhost\\c$"))
620 self.assertTrue(ntpath.ismount(b"\\\\localhost\\c$\\"))
Christian Heimesf6cd9672008-03-26 13:45:42 +0000621
Tim Goldenff64add2018-07-25 14:36:54 +0100622 def assertEqualCI(self, s1, s2):
623 """Assert that two strings are equal ignoring case differences."""
624 self.assertEqual(s1.lower(), s2.lower())
625
Steve Dower23ad6d02018-02-22 10:39:10 -0800626 @unittest.skipUnless(nt, "OS helpers require 'nt' module")
627 def test_nt_helpers(self):
628 # Trivial validation that the helpers do not break, and support both
629 # unicode and bytes (UTF-8) paths
630
Tim Goldenff64add2018-07-25 14:36:54 +0100631 executable = nt._getfinalpathname(sys.executable)
632
633 for path in executable, os.fsencode(executable):
634 volume_path = nt._getvolumepathname(path)
635 path_drive = ntpath.splitdrive(path)[0]
636 volume_path_drive = ntpath.splitdrive(volume_path)[0]
637 self.assertEqualCI(path_drive, volume_path_drive)
Steve Dower23ad6d02018-02-22 10:39:10 -0800638
639 cap, free = nt._getdiskusage(sys.exec_prefix)
640 self.assertGreater(cap, 0)
641 self.assertGreater(free, 0)
642 b_cap, b_free = nt._getdiskusage(sys.exec_prefix.encode())
643 # Free space may change, so only test the capacity is equal
644 self.assertEqual(b_cap, cap)
645 self.assertGreater(b_free, 0)
646
647 for path in [sys.prefix, sys.executable]:
648 final_path = nt._getfinalpathname(path)
649 self.assertIsInstance(final_path, str)
650 self.assertGreater(len(final_path), 0)
651
652 b_final_path = nt._getfinalpathname(path.encode())
653 self.assertIsInstance(b_final_path, bytes)
654 self.assertGreater(len(b_final_path), 0)
655
Ezio Melottid0dfe9a2013-01-10 03:12:50 +0200656class NtCommonTest(test_genericpath.CommonTest, unittest.TestCase):
Florent Xiclunac9c79782010-03-08 12:24:53 +0000657 pathmodule = ntpath
Serhiy Storchaka9ed707e2017-01-13 20:55:05 +0200658 attributes = ['relpath']
Florent Xiclunac9c79782010-03-08 12:24:53 +0000659
660
Brett Cannon3f9183b2016-08-26 14:44:48 -0700661class PathLikeTests(unittest.TestCase):
662
663 path = ntpath
664
Brett Cannon3f9183b2016-08-26 14:44:48 -0700665 def setUp(self):
666 self.file_name = support.TESTFN.lower()
Serhiy Storchakab21d1552018-03-02 11:53:51 +0200667 self.file_path = FakePath(support.TESTFN)
Brett Cannon3f9183b2016-08-26 14:44:48 -0700668 self.addCleanup(support.unlink, self.file_name)
669 with open(self.file_name, 'xb', 0) as file:
670 file.write(b"test_ntpath.PathLikeTests")
671
672 def assertPathEqual(self, func):
673 self.assertEqual(func(self.file_path), func(self.file_name))
674
675 def test_path_normcase(self):
676 self.assertPathEqual(self.path.normcase)
677
678 def test_path_isabs(self):
679 self.assertPathEqual(self.path.isabs)
680
681 def test_path_join(self):
Serhiy Storchakab21d1552018-03-02 11:53:51 +0200682 self.assertEqual(self.path.join('a', FakePath('b'), 'c'),
Brett Cannon3f9183b2016-08-26 14:44:48 -0700683 self.path.join('a', 'b', 'c'))
684
685 def test_path_split(self):
686 self.assertPathEqual(self.path.split)
687
688 def test_path_splitext(self):
689 self.assertPathEqual(self.path.splitext)
690
691 def test_path_splitdrive(self):
692 self.assertPathEqual(self.path.splitdrive)
693
694 def test_path_basename(self):
695 self.assertPathEqual(self.path.basename)
696
697 def test_path_dirname(self):
698 self.assertPathEqual(self.path.dirname)
699
700 def test_path_islink(self):
701 self.assertPathEqual(self.path.islink)
702
703 def test_path_lexists(self):
704 self.assertPathEqual(self.path.lexists)
705
706 def test_path_ismount(self):
707 self.assertPathEqual(self.path.ismount)
708
709 def test_path_expanduser(self):
710 self.assertPathEqual(self.path.expanduser)
711
712 def test_path_expandvars(self):
713 self.assertPathEqual(self.path.expandvars)
714
715 def test_path_normpath(self):
716 self.assertPathEqual(self.path.normpath)
717
718 def test_path_abspath(self):
719 self.assertPathEqual(self.path.abspath)
720
721 def test_path_realpath(self):
722 self.assertPathEqual(self.path.realpath)
723
724 def test_path_relpath(self):
725 self.assertPathEqual(self.path.relpath)
726
727 def test_path_commonpath(self):
728 common_path = self.path.commonpath([self.file_path, self.file_name])
729 self.assertEqual(common_path, self.file_name)
730
731 def test_path_isdir(self):
732 self.assertPathEqual(self.path.isdir)
733
734
Christian Heimesf6cd9672008-03-26 13:45:42 +0000735if __name__ == "__main__":
736 unittest.main()