diff -r d9c98730e2e8 -r 3d38f4640817 Lib/ntpath.py --- a/Lib/ntpath.py Sat Jul 07 13:34:50 2012 +1000 +++ b/Lib/ntpath.py Sat Jul 07 18:30:05 2012 +0200 @@ -71,11 +71,35 @@ else: return ':' -def _get_special(path): +def _get_device_prefix(path): if isinstance(path, bytes): - return (b'\\\\.\\', b'\\\\?\\') + return b'\\\\.\\' else: - return ('\\\\.\\', '\\\\?\\') + return '\\\\.\\' + + +def _get_literal_prefix(path): + if isinstance(path, bytes): + return b'\\\\?\\' + else: + return '\\\\?\\' + + +def _get_question_mark(path): + if isinstance(path, bytes): + return b'?' + else: + return '?' + + +def _get_letters(path): + import string + + if isinstance(path, bytes): + return string.ascii_letters.encode('utf-8') + else: + return string.ascii_letters + # Normalize the case of a pathname and map slashes to backslashes. # Other normalizations (such as optimizing '../' away) are not done @@ -530,13 +554,27 @@ """Normalize path, eliminating double slashes, etc.""" sep = _get_sep(path) dotdot = _get_dot(path) * 2 - special_prefixes = _get_special(path) - if path.startswith(special_prefixes): + device_prefix = _get_device_prefix(path) + question_mark = _get_question_mark(path) + colon = _get_colon(path) + letters = _get_letters(path) + is_literal = False + + if len(path) >= 6 and path[2:3] == question_mark: + # we may have a unc for a network path of a local drive, check if we + # have path[4] to be : from the and a drive letter in path[3] because + # somehting like \\?\C:\ + if path[5:6] == colon and path[4:5] in letters: + path = path[4:] + is_literal = True + else: + return path + elif path.startswith(device_prefix): # in the case of paths with these prefixes: # \\.\ -> device names - # \\?\ -> literal paths # do not do any normalization, but return the path unchanged return path + path = path.replace(_get_altsep(path), sep) prefix, path = splitdrive(path) @@ -563,6 +601,8 @@ # If the path is now empty, substitute '.' if not prefix and not comps: comps.append(_get_dot(path)) + if is_literal: + prefix = _get_literal_prefix(path) + prefix return prefix + sep.join(comps) diff -r d9c98730e2e8 -r 3d38f4640817 Lib/test/test_ntpath.py --- a/Lib/test/test_ntpath.py Sat Jul 07 13:34:50 2012 +1000 +++ b/Lib/test/test_ntpath.py Sat Jul 07 18:30:05 2012 +0200 @@ -160,27 +160,38 @@ tester("ntpath.normpath('A/./B')", r'A\B') tester("ntpath.normpath('A/foo/../B')", r'A\B') tester("ntpath.normpath('C:A//B')", r'C:A\B') + tester("ntpath.normpath('\\\\?\\C:A//B')", r'\\?\C:A\B') tester("ntpath.normpath('D:A/./B')", r'D:A\B') + tester("ntpath.normpath('\\\\?\\D:A/./B')", r'\\?\D:A\B') tester("ntpath.normpath('e:A/foo/../B')", r'e:A\B') + tester("ntpath.normpath('\\\\?\\e:A/foo/../B')", r'\\?\e:A\B') tester("ntpath.normpath('C:///A//B')", r'C:\A\B') + tester("ntpath.normpath('\\\\?\\C:///A//B')", r'\\?\C:\A\B') tester("ntpath.normpath('D:///A/./B')", r'D:\A\B') + tester("ntpath.normpath('\\\\?\\D:///A/./B')", r'\\?\D:\A\B') tester("ntpath.normpath('e:///A/foo/../B')", r'e:\A\B') + tester("ntpath.normpath('\\\\?\\e:///A/foo/../B')", r'\\?\e:\A\B') tester("ntpath.normpath('..')", r'..') tester("ntpath.normpath('.')", r'.') tester("ntpath.normpath('')", r'.') tester("ntpath.normpath('/')", '\\') tester("ntpath.normpath('c:/')", 'c:\\') + tester("ntpath.normpath('\\\\?\\c:/')", '\\\\?\\c:\\') tester("ntpath.normpath('/../.././..')", '\\') tester("ntpath.normpath('c:/../../..')", 'c:\\') + tester("ntpath.normpath('\\\\?\\c:/../../..')", '\\\\?\\c:\\') tester("ntpath.normpath('../.././..')", r'..\..\..') tester("ntpath.normpath('K:../.././..')", r'K:..\..\..') + tester("ntpath.normpath('\\\\?\\K:../.././..')", r'\\?\K:..\..\..') tester("ntpath.normpath('C:////a/b')", r'C:\a\b') + tester("ntpath.normpath('\\\\?\\C:////a/b')", r'\\?\C:\a\b') tester("ntpath.normpath('//machine/share//a/b')", r'\\machine\share\a\b') tester("ntpath.normpath('\\\\.\\NUL')", r'\\.\NUL') - tester("ntpath.normpath('\\\\?\\D:/XY\\Z')", r'\\?\D:/XY\Z') + tester("ntpath.normpath('\\\\?\\MachineName/XY\\Z')", + r'\\?\MachineName/XY\Z') def test_expandvars(self): with support.EnvironmentVarGuard() as env: