1 import ntpath
2 import os
3 import string
4 import sys
5 import unittest
6 import warnings
7 from test.support import os_helper
8 from test.support import TestFailed, is_emscripten
9 from test.support.os_helper import FakePath
10 from test import test_genericpath
11 from tempfile import TemporaryFile
12
13
14 try:
15 import nt
16 except ImportError:
17 # Most tests can complete without the nt module,
18 # but for those that require it we import here.
19 nt = None
20
21 try:
22 ntpath._getfinalpathname
23 except AttributeError:
24 HAVE_GETFINALPATHNAME = False
25 else:
26 HAVE_GETFINALPATHNAME = True
27
28 try:
29 import ctypes
30 except ImportError:
31 HAVE_GETSHORTPATHNAME = False
32 else:
33 HAVE_GETSHORTPATHNAME = True
34 def _getshortpathname(path):
35 GSPN = ctypes.WinDLL("kernel32", use_last_error=True).GetShortPathNameW
36 GSPN.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32]
37 GSPN.restype = ctypes.c_uint32
38 result_len = GSPN(path, None, 0)
39 if not result_len:
40 raise OSError("failed to get short path name 0x{:08X}"
41 .format(ctypes.get_last_error()))
42 result = ctypes.create_unicode_buffer(result_len)
43 result_len = GSPN(path, result, result_len)
44 return result[:result_len]
45
46 def _norm(path):
47 if isinstance(path, (bytes, str, os.PathLike)):
48 return ntpath.normcase(os.fsdecode(path))
49 elif hasattr(path, "__iter__"):
50 return tuple(ntpath.normcase(os.fsdecode(p)) for p in path)
51 return path
52
53
54 def tester(fn, wantResult):
55 fn = fn.replace("\\", "\\\\")
56 gotResult = eval(fn)
57 if wantResult != gotResult and _norm(wantResult) != _norm(gotResult):
58 raise TestFailed("%s should return: %s but returned: %s" \
59 %(str(fn), str(wantResult), str(gotResult)))
60
61 # then with bytes
62 fn = fn.replace("('", "(b'")
63 fn = fn.replace('("', '(b"')
64 fn = fn.replace("['", "[b'")
65 fn = fn.replace('["', '[b"')
66 fn = fn.replace(", '", ", b'")
67 fn = fn.replace(', "', ', b"')
68 fn = os.fsencode(fn).decode('latin1')
69 fn = fn.encode('ascii', 'backslashreplace').decode('ascii')
70 with warnings.catch_warnings():
71 warnings.simplefilter("ignore", DeprecationWarning)
72 gotResult = eval(fn)
73 if _norm(wantResult) != _norm(gotResult):
74 raise TestFailed("%s should return: %s but returned: %s" \
75 %(str(fn), str(wantResult), repr(gotResult)))
76
77
78 class ESC[4;38;5;81mNtpathTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
79 def assertPathEqual(self, path1, path2):
80 if path1 == path2 or _norm(path1) == _norm(path2):
81 return
82 self.assertEqual(path1, path2)
83
84 def assertPathIn(self, path, pathset):
85 self.assertIn(_norm(path), _norm(pathset))
86
87
88 class ESC[4;38;5;81mTestNtpath(ESC[4;38;5;149mNtpathTestCase):
89 def test_splitext(self):
90 tester('ntpath.splitext("foo.ext")', ('foo', '.ext'))
91 tester('ntpath.splitext("/foo/foo.ext")', ('/foo/foo', '.ext'))
92 tester('ntpath.splitext(".ext")', ('.ext', ''))
93 tester('ntpath.splitext("\\foo.ext\\foo")', ('\\foo.ext\\foo', ''))
94 tester('ntpath.splitext("foo.ext\\")', ('foo.ext\\', ''))
95 tester('ntpath.splitext("")', ('', ''))
96 tester('ntpath.splitext("foo.bar.ext")', ('foo.bar', '.ext'))
97 tester('ntpath.splitext("xx/foo.bar.ext")', ('xx/foo.bar', '.ext'))
98 tester('ntpath.splitext("xx\\foo.bar.ext")', ('xx\\foo.bar', '.ext'))
99 tester('ntpath.splitext("c:a/b\\c.d")', ('c:a/b\\c', '.d'))
100
101 def test_splitdrive(self):
102 tester('ntpath.splitdrive("c:\\foo\\bar")',
103 ('c:', '\\foo\\bar'))
104 tester('ntpath.splitdrive("c:/foo/bar")',
105 ('c:', '/foo/bar'))
106 tester('ntpath.splitdrive("\\\\conky\\mountpoint\\foo\\bar")',
107 ('\\\\conky\\mountpoint', '\\foo\\bar'))
108 tester('ntpath.splitdrive("//conky/mountpoint/foo/bar")',
109 ('//conky/mountpoint', '/foo/bar'))
110 tester('ntpath.splitdrive("\\\\\\conky\\mountpoint\\foo\\bar")',
111 ('\\\\\\conky', '\\mountpoint\\foo\\bar'))
112 tester('ntpath.splitdrive("///conky/mountpoint/foo/bar")',
113 ('///conky', '/mountpoint/foo/bar'))
114 tester('ntpath.splitdrive("\\\\conky\\\\mountpoint\\foo\\bar")',
115 ('\\\\conky\\', '\\mountpoint\\foo\\bar'))
116 tester('ntpath.splitdrive("//conky//mountpoint/foo/bar")',
117 ('//conky/', '/mountpoint/foo/bar'))
118 # Issue #19911: UNC part containing U+0130
119 self.assertEqual(ntpath.splitdrive('//conky/MOUNTPOİNT/foo/bar'),
120 ('//conky/MOUNTPOİNT', '/foo/bar'))
121
122 # gh-81790: support device namespace, including UNC drives.
123 tester('ntpath.splitdrive("//?/c:")', ("//?/c:", ""))
124 tester('ntpath.splitdrive("//?/c:/")', ("//?/c:", "/"))
125 tester('ntpath.splitdrive("//?/c:/dir")', ("//?/c:", "/dir"))
126 tester('ntpath.splitdrive("//?/UNC")', ("//?/UNC", ""))
127 tester('ntpath.splitdrive("//?/UNC/")', ("//?/UNC/", ""))
128 tester('ntpath.splitdrive("//?/UNC/server/")', ("//?/UNC/server/", ""))
129 tester('ntpath.splitdrive("//?/UNC/server/share")', ("//?/UNC/server/share", ""))
130 tester('ntpath.splitdrive("//?/UNC/server/share/dir")', ("//?/UNC/server/share", "/dir"))
131 tester('ntpath.splitdrive("//?/VOLUME{00000000-0000-0000-0000-000000000000}/spam")',
132 ('//?/VOLUME{00000000-0000-0000-0000-000000000000}', '/spam'))
133 tester('ntpath.splitdrive("//?/BootPartition/")', ("//?/BootPartition", "/"))
134
135 tester('ntpath.splitdrive("\\\\?\\c:")', ("\\\\?\\c:", ""))
136 tester('ntpath.splitdrive("\\\\?\\c:\\")', ("\\\\?\\c:", "\\"))
137 tester('ntpath.splitdrive("\\\\?\\c:\\dir")', ("\\\\?\\c:", "\\dir"))
138 tester('ntpath.splitdrive("\\\\?\\UNC")', ("\\\\?\\UNC", ""))
139 tester('ntpath.splitdrive("\\\\?\\UNC\\")', ("\\\\?\\UNC\\", ""))
140 tester('ntpath.splitdrive("\\\\?\\UNC\\server\\")', ("\\\\?\\UNC\\server\\", ""))
141 tester('ntpath.splitdrive("\\\\?\\UNC\\server\\share")', ("\\\\?\\UNC\\server\\share", ""))
142 tester('ntpath.splitdrive("\\\\?\\UNC\\server\\share\\dir")',
143 ("\\\\?\\UNC\\server\\share", "\\dir"))
144 tester('ntpath.splitdrive("\\\\?\\VOLUME{00000000-0000-0000-0000-000000000000}\\spam")',
145 ('\\\\?\\VOLUME{00000000-0000-0000-0000-000000000000}', '\\spam'))
146 tester('ntpath.splitdrive("\\\\?\\BootPartition\\")', ("\\\\?\\BootPartition", "\\"))
147
148 # gh-96290: support partial/invalid UNC drives
149 tester('ntpath.splitdrive("//")', ("//", "")) # empty server & missing share
150 tester('ntpath.splitdrive("///")', ("///", "")) # empty server & empty share
151 tester('ntpath.splitdrive("///y")', ("///y", "")) # empty server & non-empty share
152 tester('ntpath.splitdrive("//x")', ("//x", "")) # non-empty server & missing share
153 tester('ntpath.splitdrive("//x/")', ("//x/", "")) # non-empty server & empty share
154
155 def test_split(self):
156 tester('ntpath.split("c:\\foo\\bar")', ('c:\\foo', 'bar'))
157 tester('ntpath.split("\\\\conky\\mountpoint\\foo\\bar")',
158 ('\\\\conky\\mountpoint\\foo', 'bar'))
159
160 tester('ntpath.split("c:\\")', ('c:\\', ''))
161 tester('ntpath.split("\\\\conky\\mountpoint\\")',
162 ('\\\\conky\\mountpoint\\', ''))
163
164 tester('ntpath.split("c:/")', ('c:/', ''))
165 tester('ntpath.split("//conky/mountpoint/")', ('//conky/mountpoint/', ''))
166
167 def test_isabs(self):
168 tester('ntpath.isabs("c:\\")', 1)
169 tester('ntpath.isabs("\\\\conky\\mountpoint\\")', 1)
170 tester('ntpath.isabs("\\foo")', 1)
171 tester('ntpath.isabs("\\foo\\bar")', 1)
172
173 # gh-96290: normal UNC paths and device paths without trailing backslashes
174 tester('ntpath.isabs("\\\\conky\\mountpoint")', 1)
175 tester('ntpath.isabs("\\\\.\\C:")', 1)
176
177 def test_commonprefix(self):
178 tester('ntpath.commonprefix(["/home/swenson/spam", "/home/swen/spam"])',
179 "/home/swen")
180 tester('ntpath.commonprefix(["\\home\\swen\\spam", "\\home\\swen\\eggs"])',
181 "\\home\\swen\\")
182 tester('ntpath.commonprefix(["/home/swen/spam", "/home/swen/spam"])',
183 "/home/swen/spam")
184
185 def test_join(self):
186 tester('ntpath.join("")', '')
187 tester('ntpath.join("", "", "")', '')
188 tester('ntpath.join("a")', 'a')
189 tester('ntpath.join("/a")', '/a')
190 tester('ntpath.join("\\a")', '\\a')
191 tester('ntpath.join("a:")', 'a:')
192 tester('ntpath.join("a:", "\\b")', 'a:\\b')
193 tester('ntpath.join("a", "\\b")', '\\b')
194 tester('ntpath.join("a", "b", "c")', 'a\\b\\c')
195 tester('ntpath.join("a\\", "b", "c")', 'a\\b\\c')
196 tester('ntpath.join("a", "b\\", "c")', 'a\\b\\c')
197 tester('ntpath.join("a", "b", "\\c")', '\\c')
198 tester('ntpath.join("d:\\", "\\pleep")', 'd:\\pleep')
199 tester('ntpath.join("d:\\", "a", "b")', 'd:\\a\\b')
200
201 tester("ntpath.join('', 'a')", 'a')
202 tester("ntpath.join('', '', '', '', 'a')", 'a')
203 tester("ntpath.join('a', '')", 'a\\')
204 tester("ntpath.join('a', '', '', '', '')", 'a\\')
205 tester("ntpath.join('a\\', '')", 'a\\')
206 tester("ntpath.join('a\\', '', '', '', '')", 'a\\')
207 tester("ntpath.join('a/', '')", 'a/')
208
209 tester("ntpath.join('a/b', 'x/y')", 'a/b\\x/y')
210 tester("ntpath.join('/a/b', 'x/y')", '/a/b\\x/y')
211 tester("ntpath.join('/a/b/', 'x/y')", '/a/b/x/y')
212 tester("ntpath.join('c:', 'x/y')", 'c:x/y')
213 tester("ntpath.join('c:a/b', 'x/y')", 'c:a/b\\x/y')
214 tester("ntpath.join('c:a/b/', 'x/y')", 'c:a/b/x/y')
215 tester("ntpath.join('c:/', 'x/y')", 'c:/x/y')
216 tester("ntpath.join('c:/a/b', 'x/y')", 'c:/a/b\\x/y')
217 tester("ntpath.join('c:/a/b/', 'x/y')", 'c:/a/b/x/y')
218 tester("ntpath.join('//computer/share', 'x/y')", '//computer/share\\x/y')
219 tester("ntpath.join('//computer/share/', 'x/y')", '//computer/share/x/y')
220 tester("ntpath.join('//computer/share/a/b', 'x/y')", '//computer/share/a/b\\x/y')
221
222 tester("ntpath.join('a/b', '/x/y')", '/x/y')
223 tester("ntpath.join('/a/b', '/x/y')", '/x/y')
224 tester("ntpath.join('c:', '/x/y')", 'c:/x/y')
225 tester("ntpath.join('c:a/b', '/x/y')", 'c:/x/y')
226 tester("ntpath.join('c:/', '/x/y')", 'c:/x/y')
227 tester("ntpath.join('c:/a/b', '/x/y')", 'c:/x/y')
228 tester("ntpath.join('//computer/share', '/x/y')", '//computer/share/x/y')
229 tester("ntpath.join('//computer/share/', '/x/y')", '//computer/share/x/y')
230 tester("ntpath.join('//computer/share/a', '/x/y')", '//computer/share/x/y')
231
232 tester("ntpath.join('c:', 'C:x/y')", 'C:x/y')
233 tester("ntpath.join('c:a/b', 'C:x/y')", 'C:a/b\\x/y')
234 tester("ntpath.join('c:/', 'C:x/y')", 'C:/x/y')
235 tester("ntpath.join('c:/a/b', 'C:x/y')", 'C:/a/b\\x/y')
236
237 for x in ('', 'a/b', '/a/b', 'c:', 'c:a/b', 'c:/', 'c:/a/b',
238 '//computer/share', '//computer/share/', '//computer/share/a/b'):
239 for y in ('d:', 'd:x/y', 'd:/', 'd:/x/y',
240 '//machine/common', '//machine/common/', '//machine/common/x/y'):
241 tester("ntpath.join(%r, %r)" % (x, y), y)
242
243 tester("ntpath.join('\\\\computer\\share\\', 'a', 'b')", '\\\\computer\\share\\a\\b')
244 tester("ntpath.join('\\\\computer\\share', 'a', 'b')", '\\\\computer\\share\\a\\b')
245 tester("ntpath.join('\\\\computer\\share', 'a\\b')", '\\\\computer\\share\\a\\b')
246 tester("ntpath.join('//computer/share/', 'a', 'b')", '//computer/share/a\\b')
247 tester("ntpath.join('//computer/share', 'a', 'b')", '//computer/share\\a\\b')
248 tester("ntpath.join('//computer/share', 'a/b')", '//computer/share\\a/b')
249
250 def test_normpath(self):
251 tester("ntpath.normpath('A//////././//.//B')", r'A\B')
252 tester("ntpath.normpath('A/./B')", r'A\B')
253 tester("ntpath.normpath('A/foo/../B')", r'A\B')
254 tester("ntpath.normpath('C:A//B')", r'C:A\B')
255 tester("ntpath.normpath('D:A/./B')", r'D:A\B')
256 tester("ntpath.normpath('e:A/foo/../B')", r'e:A\B')
257
258 tester("ntpath.normpath('C:///A//B')", r'C:\A\B')
259 tester("ntpath.normpath('D:///A/./B')", r'D:\A\B')
260 tester("ntpath.normpath('e:///A/foo/../B')", r'e:\A\B')
261
262 tester("ntpath.normpath('..')", r'..')
263 tester("ntpath.normpath('.')", r'.')
264 tester("ntpath.normpath('')", r'.')
265 tester("ntpath.normpath('/')", '\\')
266 tester("ntpath.normpath('c:/')", 'c:\\')
267 tester("ntpath.normpath('/../.././..')", '\\')
268 tester("ntpath.normpath('c:/../../..')", 'c:\\')
269 tester("ntpath.normpath('../.././..')", r'..\..\..')
270 tester("ntpath.normpath('K:../.././..')", r'K:..\..\..')
271 tester("ntpath.normpath('C:////a/b')", r'C:\a\b')
272 tester("ntpath.normpath('//machine/share//a/b')", r'\\machine\share\a\b')
273
274 tester("ntpath.normpath('\\\\.\\NUL')", r'\\.\NUL')
275 tester("ntpath.normpath('\\\\?\\D:/XY\\Z')", r'\\?\D:/XY\Z')
276 tester("ntpath.normpath('handbook/../../Tests/image.png')", r'..\Tests\image.png')
277 tester("ntpath.normpath('handbook/../../../Tests/image.png')", r'..\..\Tests\image.png')
278 tester("ntpath.normpath('handbook///../a/.././../b/c')", r'..\b\c')
279 tester("ntpath.normpath('handbook/a/../..///../../b/c')", r'..\..\b\c')
280
281 tester("ntpath.normpath('//server/share/..')" , '\\\\server\\share\\')
282 tester("ntpath.normpath('//server/share/../')" , '\\\\server\\share\\')
283 tester("ntpath.normpath('//server/share/../..')", '\\\\server\\share\\')
284 tester("ntpath.normpath('//server/share/../../')", '\\\\server\\share\\')
285
286 # gh-96290: don't normalize partial/invalid UNC drives as rooted paths.
287 tester("ntpath.normpath('\\\\foo\\\\')", '\\\\foo\\\\')
288 tester("ntpath.normpath('\\\\foo\\')", '\\\\foo\\')
289 tester("ntpath.normpath('\\\\foo')", '\\\\foo')
290 tester("ntpath.normpath('\\\\')", '\\\\')
291
292 def test_realpath_curdir(self):
293 expected = ntpath.normpath(os.getcwd())
294 tester("ntpath.realpath('.')", expected)
295 tester("ntpath.realpath('./.')", expected)
296 tester("ntpath.realpath('/'.join(['.'] * 100))", expected)
297 tester("ntpath.realpath('.\\.')", expected)
298 tester("ntpath.realpath('\\'.join(['.'] * 100))", expected)
299
300 def test_realpath_pardir(self):
301 expected = ntpath.normpath(os.getcwd())
302 tester("ntpath.realpath('..')", ntpath.dirname(expected))
303 tester("ntpath.realpath('../..')",
304 ntpath.dirname(ntpath.dirname(expected)))
305 tester("ntpath.realpath('/'.join(['..'] * 50))",
306 ntpath.splitdrive(expected)[0] + '\\')
307 tester("ntpath.realpath('..\\..')",
308 ntpath.dirname(ntpath.dirname(expected)))
309 tester("ntpath.realpath('\\'.join(['..'] * 50))",
310 ntpath.splitdrive(expected)[0] + '\\')
311
312 @os_helper.skip_unless_symlink
313 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
314 def test_realpath_basic(self):
315 ABSTFN = ntpath.abspath(os_helper.TESTFN)
316 open(ABSTFN, "wb").close()
317 self.addCleanup(os_helper.unlink, ABSTFN)
318 self.addCleanup(os_helper.unlink, ABSTFN + "1")
319
320 os.symlink(ABSTFN, ABSTFN + "1")
321 self.assertPathEqual(ntpath.realpath(ABSTFN + "1"), ABSTFN)
322 self.assertPathEqual(ntpath.realpath(os.fsencode(ABSTFN + "1")),
323 os.fsencode(ABSTFN))
324
325 # gh-88013: call ntpath.realpath with binary drive name may raise a
326 # TypeError. The drive should not exist to reproduce the bug.
327 for c in string.ascii_uppercase:
328 d = f"{c}:\\"
329 if not ntpath.exists(d):
330 break
331 else:
332 raise OSError("No free drive letters available")
333 self.assertEqual(ntpath.realpath(d), d)
334
335 # gh-106242: Embedded nulls and non-strict fallback to abspath
336 self.assertEqual(ABSTFN + "\0spam",
337 ntpath.realpath(os_helper.TESTFN + "\0spam", strict=False))
338
339 @os_helper.skip_unless_symlink
340 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
341 def test_realpath_strict(self):
342 # Bug #43757: raise FileNotFoundError in strict mode if we encounter
343 # a path that does not exist.
344 ABSTFN = ntpath.abspath(os_helper.TESTFN)
345 os.symlink(ABSTFN + "1", ABSTFN)
346 self.addCleanup(os_helper.unlink, ABSTFN)
347 self.assertRaises(FileNotFoundError, ntpath.realpath, ABSTFN, strict=True)
348 self.assertRaises(FileNotFoundError, ntpath.realpath, ABSTFN + "2", strict=True)
349 # gh-106242: Embedded nulls should raise OSError (not ValueError)
350 self.assertRaises(OSError, ntpath.realpath, ABSTFN + "\0spam", strict=True)
351
352 @os_helper.skip_unless_symlink
353 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
354 def test_realpath_relative(self):
355 ABSTFN = ntpath.abspath(os_helper.TESTFN)
356 open(ABSTFN, "wb").close()
357 self.addCleanup(os_helper.unlink, ABSTFN)
358 self.addCleanup(os_helper.unlink, ABSTFN + "1")
359
360 os.symlink(ABSTFN, ntpath.relpath(ABSTFN + "1"))
361 self.assertPathEqual(ntpath.realpath(ABSTFN + "1"), ABSTFN)
362
363 @os_helper.skip_unless_symlink
364 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
365 def test_realpath_broken_symlinks(self):
366 ABSTFN = ntpath.abspath(os_helper.TESTFN)
367 os.mkdir(ABSTFN)
368 self.addCleanup(os_helper.rmtree, ABSTFN)
369
370 with os_helper.change_cwd(ABSTFN):
371 os.mkdir("subdir")
372 os.chdir("subdir")
373 os.symlink(".", "recursive")
374 os.symlink("..", "parent")
375 os.chdir("..")
376 os.symlink(".", "self")
377 os.symlink("missing", "broken")
378 os.symlink(r"broken\bar", "broken1")
379 os.symlink(r"self\self\broken", "broken2")
380 os.symlink(r"subdir\parent\subdir\parent\broken", "broken3")
381 os.symlink(ABSTFN + r"\broken", "broken4")
382 os.symlink(r"recursive\..\broken", "broken5")
383
384 self.assertPathEqual(ntpath.realpath("broken"),
385 ABSTFN + r"\missing")
386 self.assertPathEqual(ntpath.realpath(r"broken\foo"),
387 ABSTFN + r"\missing\foo")
388 # bpo-38453: We no longer recursively resolve segments of relative
389 # symlinks that the OS cannot resolve.
390 self.assertPathEqual(ntpath.realpath(r"broken1"),
391 ABSTFN + r"\broken\bar")
392 self.assertPathEqual(ntpath.realpath(r"broken1\baz"),
393 ABSTFN + r"\broken\bar\baz")
394 self.assertPathEqual(ntpath.realpath("broken2"),
395 ABSTFN + r"\self\self\missing")
396 self.assertPathEqual(ntpath.realpath("broken3"),
397 ABSTFN + r"\subdir\parent\subdir\parent\missing")
398 self.assertPathEqual(ntpath.realpath("broken4"),
399 ABSTFN + r"\missing")
400 self.assertPathEqual(ntpath.realpath("broken5"),
401 ABSTFN + r"\missing")
402
403 self.assertPathEqual(ntpath.realpath(b"broken"),
404 os.fsencode(ABSTFN + r"\missing"))
405 self.assertPathEqual(ntpath.realpath(rb"broken\foo"),
406 os.fsencode(ABSTFN + r"\missing\foo"))
407 self.assertPathEqual(ntpath.realpath(rb"broken1"),
408 os.fsencode(ABSTFN + r"\broken\bar"))
409 self.assertPathEqual(ntpath.realpath(rb"broken1\baz"),
410 os.fsencode(ABSTFN + r"\broken\bar\baz"))
411 self.assertPathEqual(ntpath.realpath(b"broken2"),
412 os.fsencode(ABSTFN + r"\self\self\missing"))
413 self.assertPathEqual(ntpath.realpath(rb"broken3"),
414 os.fsencode(ABSTFN + r"\subdir\parent\subdir\parent\missing"))
415 self.assertPathEqual(ntpath.realpath(b"broken4"),
416 os.fsencode(ABSTFN + r"\missing"))
417 self.assertPathEqual(ntpath.realpath(b"broken5"),
418 os.fsencode(ABSTFN + r"\missing"))
419
420 @os_helper.skip_unless_symlink
421 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
422 def test_realpath_symlink_loops(self):
423 # Symlink loops in non-strict mode are non-deterministic as to which
424 # path is returned, but it will always be the fully resolved path of
425 # one member of the cycle
426 ABSTFN = ntpath.abspath(os_helper.TESTFN)
427 self.addCleanup(os_helper.unlink, ABSTFN)
428 self.addCleanup(os_helper.unlink, ABSTFN + "1")
429 self.addCleanup(os_helper.unlink, ABSTFN + "2")
430 self.addCleanup(os_helper.unlink, ABSTFN + "y")
431 self.addCleanup(os_helper.unlink, ABSTFN + "c")
432 self.addCleanup(os_helper.unlink, ABSTFN + "a")
433
434 os.symlink(ABSTFN, ABSTFN)
435 self.assertPathEqual(ntpath.realpath(ABSTFN), ABSTFN)
436
437 os.symlink(ABSTFN + "1", ABSTFN + "2")
438 os.symlink(ABSTFN + "2", ABSTFN + "1")
439 expected = (ABSTFN + "1", ABSTFN + "2")
440 self.assertPathIn(ntpath.realpath(ABSTFN + "1"), expected)
441 self.assertPathIn(ntpath.realpath(ABSTFN + "2"), expected)
442
443 self.assertPathIn(ntpath.realpath(ABSTFN + "1\\x"),
444 (ntpath.join(r, "x") for r in expected))
445 self.assertPathEqual(ntpath.realpath(ABSTFN + "1\\.."),
446 ntpath.dirname(ABSTFN))
447 self.assertPathEqual(ntpath.realpath(ABSTFN + "1\\..\\x"),
448 ntpath.dirname(ABSTFN) + "\\x")
449 os.symlink(ABSTFN + "x", ABSTFN + "y")
450 self.assertPathEqual(ntpath.realpath(ABSTFN + "1\\..\\"
451 + ntpath.basename(ABSTFN) + "y"),
452 ABSTFN + "x")
453 self.assertPathIn(ntpath.realpath(ABSTFN + "1\\..\\"
454 + ntpath.basename(ABSTFN) + "1"),
455 expected)
456
457 os.symlink(ntpath.basename(ABSTFN) + "a\\b", ABSTFN + "a")
458 self.assertPathEqual(ntpath.realpath(ABSTFN + "a"), ABSTFN + "a")
459
460 os.symlink("..\\" + ntpath.basename(ntpath.dirname(ABSTFN))
461 + "\\" + ntpath.basename(ABSTFN) + "c", ABSTFN + "c")
462 self.assertPathEqual(ntpath.realpath(ABSTFN + "c"), ABSTFN + "c")
463
464 # Test using relative path as well.
465 self.assertPathEqual(ntpath.realpath(ntpath.basename(ABSTFN)), ABSTFN)
466
467 @os_helper.skip_unless_symlink
468 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
469 def test_realpath_symlink_loops_strict(self):
470 # Symlink loops raise OSError in strict mode
471 ABSTFN = ntpath.abspath(os_helper.TESTFN)
472 self.addCleanup(os_helper.unlink, ABSTFN)
473 self.addCleanup(os_helper.unlink, ABSTFN + "1")
474 self.addCleanup(os_helper.unlink, ABSTFN + "2")
475 self.addCleanup(os_helper.unlink, ABSTFN + "y")
476 self.addCleanup(os_helper.unlink, ABSTFN + "c")
477 self.addCleanup(os_helper.unlink, ABSTFN + "a")
478
479 os.symlink(ABSTFN, ABSTFN)
480 self.assertRaises(OSError, ntpath.realpath, ABSTFN, strict=True)
481
482 os.symlink(ABSTFN + "1", ABSTFN + "2")
483 os.symlink(ABSTFN + "2", ABSTFN + "1")
484 self.assertRaises(OSError, ntpath.realpath, ABSTFN + "1", strict=True)
485 self.assertRaises(OSError, ntpath.realpath, ABSTFN + "2", strict=True)
486 self.assertRaises(OSError, ntpath.realpath, ABSTFN + "1\\x", strict=True)
487 # Windows eliminates '..' components before resolving links, so the
488 # following call is not expected to raise.
489 self.assertPathEqual(ntpath.realpath(ABSTFN + "1\\..", strict=True),
490 ntpath.dirname(ABSTFN))
491 self.assertRaises(OSError, ntpath.realpath, ABSTFN + "1\\..\\x", strict=True)
492 os.symlink(ABSTFN + "x", ABSTFN + "y")
493 self.assertRaises(OSError, ntpath.realpath, ABSTFN + "1\\..\\"
494 + ntpath.basename(ABSTFN) + "y",
495 strict=True)
496 self.assertRaises(OSError, ntpath.realpath,
497 ABSTFN + "1\\..\\" + ntpath.basename(ABSTFN) + "1",
498 strict=True)
499
500 os.symlink(ntpath.basename(ABSTFN) + "a\\b", ABSTFN + "a")
501 self.assertRaises(OSError, ntpath.realpath, ABSTFN + "a", strict=True)
502
503 os.symlink("..\\" + ntpath.basename(ntpath.dirname(ABSTFN))
504 + "\\" + ntpath.basename(ABSTFN) + "c", ABSTFN + "c")
505 self.assertRaises(OSError, ntpath.realpath, ABSTFN + "c", strict=True)
506
507 # Test using relative path as well.
508 self.assertRaises(OSError, ntpath.realpath, ntpath.basename(ABSTFN),
509 strict=True)
510
511 @os_helper.skip_unless_symlink
512 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
513 def test_realpath_symlink_prefix(self):
514 ABSTFN = ntpath.abspath(os_helper.TESTFN)
515 self.addCleanup(os_helper.unlink, ABSTFN + "3")
516 self.addCleanup(os_helper.unlink, "\\\\?\\" + ABSTFN + "3.")
517 self.addCleanup(os_helper.unlink, ABSTFN + "3link")
518 self.addCleanup(os_helper.unlink, ABSTFN + "3.link")
519
520 with open(ABSTFN + "3", "wb") as f:
521 f.write(b'0')
522 os.symlink(ABSTFN + "3", ABSTFN + "3link")
523
524 with open("\\\\?\\" + ABSTFN + "3.", "wb") as f:
525 f.write(b'1')
526 os.symlink("\\\\?\\" + ABSTFN + "3.", ABSTFN + "3.link")
527
528 self.assertPathEqual(ntpath.realpath(ABSTFN + "3link"),
529 ABSTFN + "3")
530 self.assertPathEqual(ntpath.realpath(ABSTFN + "3.link"),
531 "\\\\?\\" + ABSTFN + "3.")
532
533 # Resolved paths should be usable to open target files
534 with open(ntpath.realpath(ABSTFN + "3link"), "rb") as f:
535 self.assertEqual(f.read(), b'0')
536 with open(ntpath.realpath(ABSTFN + "3.link"), "rb") as f:
537 self.assertEqual(f.read(), b'1')
538
539 # When the prefix is included, it is not stripped
540 self.assertPathEqual(ntpath.realpath("\\\\?\\" + ABSTFN + "3link"),
541 "\\\\?\\" + ABSTFN + "3")
542 self.assertPathEqual(ntpath.realpath("\\\\?\\" + ABSTFN + "3.link"),
543 "\\\\?\\" + ABSTFN + "3.")
544
545 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
546 def test_realpath_nul(self):
547 tester("ntpath.realpath('NUL')", r'\\.\NUL')
548
549 @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
550 @unittest.skipUnless(HAVE_GETSHORTPATHNAME, 'need _getshortpathname')
551 def test_realpath_cwd(self):
552 ABSTFN = ntpath.abspath(os_helper.TESTFN)
553
554 os_helper.unlink(ABSTFN)
555 os_helper.rmtree(ABSTFN)
556 os.mkdir(ABSTFN)
557 self.addCleanup(os_helper.rmtree, ABSTFN)
558
559 test_dir_long = ntpath.join(ABSTFN, "MyVeryLongDirectoryName")
560 os.mkdir(test_dir_long)
561
562 test_dir_short = _getshortpathname(test_dir_long)
563 test_file_long = ntpath.join(test_dir_long, "file.txt")
564 test_file_short = ntpath.join(test_dir_short, "file.txt")
565
566 with open(test_file_long, "wb") as f:
567 f.write(b"content")
568
569 self.assertPathEqual(test_file_long, ntpath.realpath(test_file_short))
570
571 with os_helper.change_cwd(test_dir_long):
572 self.assertPathEqual(test_file_long, ntpath.realpath("file.txt"))
573 with os_helper.change_cwd(test_dir_long.lower()):
574 self.assertPathEqual(test_file_long, ntpath.realpath("file.txt"))
575 with os_helper.change_cwd(test_dir_short):
576 self.assertPathEqual(test_file_long, ntpath.realpath("file.txt"))
577
578 def test_expandvars(self):
579 with os_helper.EnvironmentVarGuard() as env:
580 env.clear()
581 env["foo"] = "bar"
582 env["{foo"] = "baz1"
583 env["{foo}"] = "baz2"
584 tester('ntpath.expandvars("foo")', "foo")
585 tester('ntpath.expandvars("$foo bar")', "bar bar")
586 tester('ntpath.expandvars("${foo}bar")', "barbar")
587 tester('ntpath.expandvars("$[foo]bar")', "$[foo]bar")
588 tester('ntpath.expandvars("$bar bar")', "$bar bar")
589 tester('ntpath.expandvars("$?bar")', "$?bar")
590 tester('ntpath.expandvars("$foo}bar")', "bar}bar")
591 tester('ntpath.expandvars("${foo")', "${foo")
592 tester('ntpath.expandvars("${{foo}}")', "baz1}")
593 tester('ntpath.expandvars("$foo$foo")', "barbar")
594 tester('ntpath.expandvars("$bar$bar")', "$bar$bar")
595 tester('ntpath.expandvars("%foo% bar")', "bar bar")
596 tester('ntpath.expandvars("%foo%bar")', "barbar")
597 tester('ntpath.expandvars("%foo%%foo%")', "barbar")
598 tester('ntpath.expandvars("%%foo%%foo%foo%")', "%foo%foobar")
599 tester('ntpath.expandvars("%?bar%")', "%?bar%")
600 tester('ntpath.expandvars("%foo%%bar")', "bar%bar")
601 tester('ntpath.expandvars("\'%foo%\'%bar")', "\'%foo%\'%bar")
602 tester('ntpath.expandvars("bar\'%foo%")', "bar\'%foo%")
603
604 @unittest.skipUnless(os_helper.FS_NONASCII, 'need os_helper.FS_NONASCII')
605 def test_expandvars_nonascii(self):
606 def check(value, expected):
607 tester('ntpath.expandvars(%r)' % value, expected)
608 with os_helper.EnvironmentVarGuard() as env:
609 env.clear()
610 nonascii = os_helper.FS_NONASCII
611 env['spam'] = nonascii
612 env[nonascii] = 'ham' + nonascii
613 check('$spam bar', '%s bar' % nonascii)
614 check('$%s bar' % nonascii, '$%s bar' % nonascii)
615 check('${spam}bar', '%sbar' % nonascii)
616 check('${%s}bar' % nonascii, 'ham%sbar' % nonascii)
617 check('$spam}bar', '%s}bar' % nonascii)
618 check('$%s}bar' % nonascii, '$%s}bar' % nonascii)
619 check('%spam% bar', '%s bar' % nonascii)
620 check('%{}% bar'.format(nonascii), 'ham%s bar' % nonascii)
621 check('%spam%bar', '%sbar' % nonascii)
622 check('%{}%bar'.format(nonascii), 'ham%sbar' % nonascii)
623
624 def test_expanduser(self):
625 tester('ntpath.expanduser("test")', 'test')
626
627 with os_helper.EnvironmentVarGuard() as env:
628 env.clear()
629 tester('ntpath.expanduser("~test")', '~test')
630
631 env['HOMEDRIVE'] = 'C:\\'
632 env['HOMEPATH'] = 'Users\\eric'
633 env['USERNAME'] = 'eric'
634 tester('ntpath.expanduser("~test")', 'C:\\Users\\test')
635 tester('ntpath.expanduser("~")', 'C:\\Users\\eric')
636
637 del env['HOMEDRIVE']
638 tester('ntpath.expanduser("~test")', 'Users\\test')
639 tester('ntpath.expanduser("~")', 'Users\\eric')
640
641 env.clear()
642 env['USERPROFILE'] = 'C:\\Users\\eric'
643 env['USERNAME'] = 'eric'
644 tester('ntpath.expanduser("~test")', 'C:\\Users\\test')
645 tester('ntpath.expanduser("~")', 'C:\\Users\\eric')
646 tester('ntpath.expanduser("~test\\foo\\bar")',
647 'C:\\Users\\test\\foo\\bar')
648 tester('ntpath.expanduser("~test/foo/bar")',
649 'C:\\Users\\test/foo/bar')
650 tester('ntpath.expanduser("~\\foo\\bar")',
651 'C:\\Users\\eric\\foo\\bar')
652 tester('ntpath.expanduser("~/foo/bar")',
653 'C:\\Users\\eric/foo/bar')
654
655 # bpo-36264: ignore `HOME` when set on windows
656 env.clear()
657 env['HOME'] = 'F:\\'
658 env['USERPROFILE'] = 'C:\\Users\\eric'
659 env['USERNAME'] = 'eric'
660 tester('ntpath.expanduser("~test")', 'C:\\Users\\test')
661 tester('ntpath.expanduser("~")', 'C:\\Users\\eric')
662
663 # bpo-39899: don't guess another user's home directory if
664 # `%USERNAME% != basename(%USERPROFILE%)`
665 env.clear()
666 env['USERPROFILE'] = 'C:\\Users\\eric'
667 env['USERNAME'] = 'idle'
668 tester('ntpath.expanduser("~test")', '~test')
669 tester('ntpath.expanduser("~")', 'C:\\Users\\eric')
670
671
672
673 @unittest.skipUnless(nt, "abspath requires 'nt' module")
674 def test_abspath(self):
675 tester('ntpath.abspath("C:\\")', "C:\\")
676 tester('ntpath.abspath("\\\\?\\C:////spam////eggs. . .")', "\\\\?\\C:\\spam\\eggs")
677 tester('ntpath.abspath("\\\\.\\C:////spam////eggs. . .")', "\\\\.\\C:\\spam\\eggs")
678 tester('ntpath.abspath("//spam//eggs. . .")', "\\\\spam\\eggs")
679 tester('ntpath.abspath("\\\\spam\\\\eggs. . .")', "\\\\spam\\eggs")
680 tester('ntpath.abspath("C:/spam. . .")', "C:\\spam")
681 tester('ntpath.abspath("C:\\spam. . .")', "C:\\spam")
682 tester('ntpath.abspath("C:/nul")', "\\\\.\\nul")
683 tester('ntpath.abspath("C:\\nul")', "\\\\.\\nul")
684 tester('ntpath.abspath("//..")', "\\\\")
685 tester('ntpath.abspath("//../")', "\\\\..\\")
686 tester('ntpath.abspath("//../..")', "\\\\..\\")
687 tester('ntpath.abspath("//../../")', "\\\\..\\..\\")
688 tester('ntpath.abspath("//../../../")', "\\\\..\\..\\")
689 tester('ntpath.abspath("//../../../..")', "\\\\..\\..\\")
690 tester('ntpath.abspath("//../../../../")', "\\\\..\\..\\")
691 tester('ntpath.abspath("//server")', "\\\\server")
692 tester('ntpath.abspath("//server/")', "\\\\server\\")
693 tester('ntpath.abspath("//server/..")', "\\\\server\\")
694 tester('ntpath.abspath("//server/../")', "\\\\server\\..\\")
695 tester('ntpath.abspath("//server/../..")', "\\\\server\\..\\")
696 tester('ntpath.abspath("//server/../../")', "\\\\server\\..\\")
697 tester('ntpath.abspath("//server/../../..")', "\\\\server\\..\\")
698 tester('ntpath.abspath("//server/../../../")', "\\\\server\\..\\")
699 tester('ntpath.abspath("//server/share")', "\\\\server\\share")
700 tester('ntpath.abspath("//server/share/")', "\\\\server\\share\\")
701 tester('ntpath.abspath("//server/share/..")', "\\\\server\\share\\")
702 tester('ntpath.abspath("//server/share/../")', "\\\\server\\share\\")
703 tester('ntpath.abspath("//server/share/../..")', "\\\\server\\share\\")
704 tester('ntpath.abspath("//server/share/../../")', "\\\\server\\share\\")
705 tester('ntpath.abspath("C:\\nul. . .")', "\\\\.\\nul")
706 tester('ntpath.abspath("//... . .")', "\\\\")
707 tester('ntpath.abspath("//.. . . .")', "\\\\")
708 tester('ntpath.abspath("//../... . .")', "\\\\..\\")
709 tester('ntpath.abspath("//../.. . . .")', "\\\\..\\")
710 with os_helper.temp_cwd(os_helper.TESTFN) as cwd_dir: # bpo-31047
711 tester('ntpath.abspath("")', cwd_dir)
712 tester('ntpath.abspath(" ")', cwd_dir + "\\ ")
713 tester('ntpath.abspath("?")', cwd_dir + "\\?")
714 drive, _ = ntpath.splitdrive(cwd_dir)
715 tester('ntpath.abspath("/abc/")', drive + "\\abc")
716
717 def test_relpath(self):
718 tester('ntpath.relpath("a")', 'a')
719 tester('ntpath.relpath(ntpath.abspath("a"))', 'a')
720 tester('ntpath.relpath("a/b")', 'a\\b')
721 tester('ntpath.relpath("../a/b")', '..\\a\\b')
722 with os_helper.temp_cwd(os_helper.TESTFN) as cwd_dir:
723 currentdir = ntpath.basename(cwd_dir)
724 tester('ntpath.relpath("a", "../b")', '..\\'+currentdir+'\\a')
725 tester('ntpath.relpath("a/b", "../c")', '..\\'+currentdir+'\\a\\b')
726 tester('ntpath.relpath("a", "b/c")', '..\\..\\a')
727 tester('ntpath.relpath("c:/foo/bar/bat", "c:/x/y")', '..\\..\\foo\\bar\\bat')
728 tester('ntpath.relpath("//conky/mountpoint/a", "//conky/mountpoint/b/c")', '..\\..\\a')
729 tester('ntpath.relpath("a", "a")', '.')
730 tester('ntpath.relpath("/foo/bar/bat", "/x/y/z")', '..\\..\\..\\foo\\bar\\bat')
731 tester('ntpath.relpath("/foo/bar/bat", "/foo/bar")', 'bat')
732 tester('ntpath.relpath("/foo/bar/bat", "/")', 'foo\\bar\\bat')
733 tester('ntpath.relpath("/", "/foo/bar/bat")', '..\\..\\..')
734 tester('ntpath.relpath("/foo/bar/bat", "/x")', '..\\foo\\bar\\bat')
735 tester('ntpath.relpath("/x", "/foo/bar/bat")', '..\\..\\..\\x')
736 tester('ntpath.relpath("/", "/")', '.')
737 tester('ntpath.relpath("/a", "/a")', '.')
738 tester('ntpath.relpath("/a/b", "/a/b")', '.')
739 tester('ntpath.relpath("c:/foo", "C:/FOO")', '.')
740
741 def test_commonpath(self):
742 def check(paths, expected):
743 tester(('ntpath.commonpath(%r)' % paths).replace('\\\\', '\\'),
744 expected)
745 def check_error(exc, paths):
746 self.assertRaises(exc, ntpath.commonpath, paths)
747 self.assertRaises(exc, ntpath.commonpath,
748 [os.fsencode(p) for p in paths])
749
750 self.assertRaises(ValueError, ntpath.commonpath, [])
751 check_error(ValueError, ['C:\\Program Files', 'Program Files'])
752 check_error(ValueError, ['C:\\Program Files', 'C:Program Files'])
753 check_error(ValueError, ['\\Program Files', 'Program Files'])
754 check_error(ValueError, ['Program Files', 'C:\\Program Files'])
755 check(['C:\\Program Files'], 'C:\\Program Files')
756 check(['C:\\Program Files', 'C:\\Program Files'], 'C:\\Program Files')
757 check(['C:\\Program Files\\', 'C:\\Program Files'],
758 'C:\\Program Files')
759 check(['C:\\Program Files\\', 'C:\\Program Files\\'],
760 'C:\\Program Files')
761 check(['C:\\\\Program Files', 'C:\\Program Files\\\\'],
762 'C:\\Program Files')
763 check(['C:\\.\\Program Files', 'C:\\Program Files\\.'],
764 'C:\\Program Files')
765 check(['C:\\', 'C:\\bin'], 'C:\\')
766 check(['C:\\Program Files', 'C:\\bin'], 'C:\\')
767 check(['C:\\Program Files', 'C:\\Program Files\\Bar'],
768 'C:\\Program Files')
769 check(['C:\\Program Files\\Foo', 'C:\\Program Files\\Bar'],
770 'C:\\Program Files')
771 check(['C:\\Program Files', 'C:\\Projects'], 'C:\\')
772 check(['C:\\Program Files\\', 'C:\\Projects'], 'C:\\')
773
774 check(['C:\\Program Files\\Foo', 'C:/Program Files/Bar'],
775 'C:\\Program Files')
776 check(['C:\\Program Files\\Foo', 'c:/program files/bar'],
777 'C:\\Program Files')
778 check(['c:/program files/bar', 'C:\\Program Files\\Foo'],
779 'c:\\program files')
780
781 check_error(ValueError, ['C:\\Program Files', 'D:\\Program Files'])
782
783 check(['spam'], 'spam')
784 check(['spam', 'spam'], 'spam')
785 check(['spam', 'alot'], '')
786 check(['and\\jam', 'and\\spam'], 'and')
787 check(['and\\\\jam', 'and\\spam\\\\'], 'and')
788 check(['and\\.\\jam', '.\\and\\spam'], 'and')
789 check(['and\\jam', 'and\\spam', 'alot'], '')
790 check(['and\\jam', 'and\\spam', 'and'], 'and')
791 check(['C:and\\jam', 'C:and\\spam'], 'C:and')
792
793 check([''], '')
794 check(['', 'spam\\alot'], '')
795 check_error(ValueError, ['', '\\spam\\alot'])
796
797 self.assertRaises(TypeError, ntpath.commonpath,
798 [b'C:\\Program Files', 'C:\\Program Files\\Foo'])
799 self.assertRaises(TypeError, ntpath.commonpath,
800 [b'C:\\Program Files', 'Program Files\\Foo'])
801 self.assertRaises(TypeError, ntpath.commonpath,
802 [b'Program Files', 'C:\\Program Files\\Foo'])
803 self.assertRaises(TypeError, ntpath.commonpath,
804 ['C:\\Program Files', b'C:\\Program Files\\Foo'])
805 self.assertRaises(TypeError, ntpath.commonpath,
806 ['C:\\Program Files', b'Program Files\\Foo'])
807 self.assertRaises(TypeError, ntpath.commonpath,
808 ['Program Files', b'C:\\Program Files\\Foo'])
809
810 @unittest.skipIf(is_emscripten, "Emscripten cannot fstat unnamed files.")
811 def test_sameopenfile(self):
812 with TemporaryFile() as tf1, TemporaryFile() as tf2:
813 # Make sure the same file is really the same
814 self.assertTrue(ntpath.sameopenfile(tf1.fileno(), tf1.fileno()))
815 # Make sure different files are really different
816 self.assertFalse(ntpath.sameopenfile(tf1.fileno(), tf2.fileno()))
817 # Make sure invalid values don't cause issues on win32
818 if sys.platform == "win32":
819 with self.assertRaises(OSError):
820 # Invalid file descriptors shouldn't display assert
821 # dialogs (#4804)
822 ntpath.sameopenfile(-1, -1)
823
824 def test_ismount(self):
825 self.assertTrue(ntpath.ismount("c:\\"))
826 self.assertTrue(ntpath.ismount("C:\\"))
827 self.assertTrue(ntpath.ismount("c:/"))
828 self.assertTrue(ntpath.ismount("C:/"))
829 self.assertTrue(ntpath.ismount("\\\\.\\c:\\"))
830 self.assertTrue(ntpath.ismount("\\\\.\\C:\\"))
831
832 self.assertTrue(ntpath.ismount(b"c:\\"))
833 self.assertTrue(ntpath.ismount(b"C:\\"))
834 self.assertTrue(ntpath.ismount(b"c:/"))
835 self.assertTrue(ntpath.ismount(b"C:/"))
836 self.assertTrue(ntpath.ismount(b"\\\\.\\c:\\"))
837 self.assertTrue(ntpath.ismount(b"\\\\.\\C:\\"))
838
839 with os_helper.temp_dir() as d:
840 self.assertFalse(ntpath.ismount(d))
841
842 if sys.platform == "win32":
843 #
844 # Make sure the current folder isn't the root folder
845 # (or any other volume root). The drive-relative
846 # locations below cannot then refer to mount points
847 #
848 test_cwd = os.getenv("SystemRoot")
849 drive, path = ntpath.splitdrive(test_cwd)
850 with os_helper.change_cwd(test_cwd):
851 self.assertFalse(ntpath.ismount(drive.lower()))
852 self.assertFalse(ntpath.ismount(drive.upper()))
853
854 self.assertTrue(ntpath.ismount("\\\\localhost\\c$"))
855 self.assertTrue(ntpath.ismount("\\\\localhost\\c$\\"))
856
857 self.assertTrue(ntpath.ismount(b"\\\\localhost\\c$"))
858 self.assertTrue(ntpath.ismount(b"\\\\localhost\\c$\\"))
859
860 def assertEqualCI(self, s1, s2):
861 """Assert that two strings are equal ignoring case differences."""
862 self.assertEqual(s1.lower(), s2.lower())
863
864 @unittest.skipUnless(nt, "OS helpers require 'nt' module")
865 def test_nt_helpers(self):
866 # Trivial validation that the helpers do not break, and support both
867 # unicode and bytes (UTF-8) paths
868
869 executable = nt._getfinalpathname(sys.executable)
870
871 for path in executable, os.fsencode(executable):
872 volume_path = nt._getvolumepathname(path)
873 path_drive = ntpath.splitdrive(path)[0]
874 volume_path_drive = ntpath.splitdrive(volume_path)[0]
875 self.assertEqualCI(path_drive, volume_path_drive)
876
877 cap, free = nt._getdiskusage(sys.exec_prefix)
878 self.assertGreater(cap, 0)
879 self.assertGreater(free, 0)
880 b_cap, b_free = nt._getdiskusage(sys.exec_prefix.encode())
881 # Free space may change, so only test the capacity is equal
882 self.assertEqual(b_cap, cap)
883 self.assertGreater(b_free, 0)
884
885 for path in [sys.prefix, sys.executable]:
886 final_path = nt._getfinalpathname(path)
887 self.assertIsInstance(final_path, str)
888 self.assertGreater(len(final_path), 0)
889
890 b_final_path = nt._getfinalpathname(path.encode())
891 self.assertIsInstance(b_final_path, bytes)
892 self.assertGreater(len(b_final_path), 0)
893
894 class ESC[4;38;5;81mNtCommonTest(ESC[4;38;5;149mtest_genericpathESC[4;38;5;149m.ESC[4;38;5;149mCommonTest, ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
895 pathmodule = ntpath
896 attributes = ['relpath']
897
898
899 class ESC[4;38;5;81mPathLikeTests(ESC[4;38;5;149mNtpathTestCase):
900
901 path = ntpath
902
903 def setUp(self):
904 self.file_name = os_helper.TESTFN
905 self.file_path = FakePath(os_helper.TESTFN)
906 self.addCleanup(os_helper.unlink, self.file_name)
907 with open(self.file_name, 'xb', 0) as file:
908 file.write(b"test_ntpath.PathLikeTests")
909
910 def _check_function(self, func):
911 self.assertPathEqual(func(self.file_path), func(self.file_name))
912
913 def test_path_normcase(self):
914 self._check_function(self.path.normcase)
915 if sys.platform == 'win32':
916 self.assertEqual(ntpath.normcase('\u03a9\u2126'), 'ωΩ')
917 self.assertEqual(ntpath.normcase('abc\x00def'), 'abc\x00def')
918
919 def test_path_isabs(self):
920 self._check_function(self.path.isabs)
921
922 def test_path_join(self):
923 self.assertEqual(self.path.join('a', FakePath('b'), 'c'),
924 self.path.join('a', 'b', 'c'))
925
926 def test_path_split(self):
927 self._check_function(self.path.split)
928
929 def test_path_splitext(self):
930 self._check_function(self.path.splitext)
931
932 def test_path_splitdrive(self):
933 self._check_function(self.path.splitdrive)
934
935 def test_path_basename(self):
936 self._check_function(self.path.basename)
937
938 def test_path_dirname(self):
939 self._check_function(self.path.dirname)
940
941 def test_path_islink(self):
942 self._check_function(self.path.islink)
943
944 def test_path_lexists(self):
945 self._check_function(self.path.lexists)
946
947 def test_path_ismount(self):
948 self._check_function(self.path.ismount)
949
950 def test_path_expanduser(self):
951 self._check_function(self.path.expanduser)
952
953 def test_path_expandvars(self):
954 self._check_function(self.path.expandvars)
955
956 def test_path_normpath(self):
957 self._check_function(self.path.normpath)
958
959 def test_path_abspath(self):
960 self._check_function(self.path.abspath)
961
962 def test_path_realpath(self):
963 self._check_function(self.path.realpath)
964
965 def test_path_relpath(self):
966 self._check_function(self.path.relpath)
967
968 def test_path_commonpath(self):
969 common_path = self.path.commonpath([self.file_path, self.file_name])
970 self.assertPathEqual(common_path, self.file_name)
971
972 def test_path_isdir(self):
973 self._check_function(self.path.isdir)
974
975
976 if __name__ == "__main__":
977 unittest.main()