| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -87,16 +87,20 @@ def normcase(s): | |||
| 87 | 87 | def isabs(s): | |
| 88 | 88 | """Test whether a path is absolute""" | |
| 89 | 89 | s = os.fspath(s) | |
| 90 | - # Paths beginning with \\?\ are always absolute, but do not | ||
| 91 | - # necessarily contain a drive. | ||
| 92 | 90 | if isinstance(s, bytes): | |
| 93 | - if s.replace(b'/', b'\\').startswith(b'\\\\?\\'): | ||
| 94 | - return True | ||
| 91 | + sep = b'\\' | ||
| 92 | + altsep = b'/' | ||
| 93 | + colon_sep = b':\\' | ||
| 95 | 94 | else: | |
| 96 | - if s.replace('/', '\\').startswith('\\\\?\\'): | ||
| 97 | - return True | ||
| 98 | - s = splitdrive(s)[1] | ||
| 99 | - return len(s) > 0 and s[0] and s[0] in _get_bothseps(s) | ||
| 95 | + sep = '\\' | ||
| 96 | + altsep = '/' | ||
| 97 | + colon_sep = ':\\' | ||
| 98 | + s = s[:3].replace(altsep, sep) | ||
| 99 | + # Absolute: UNC, device, and paths with a drive and root. | ||
| 100 | + # LEGACY BUG: isabs("/x") should be false since the path has no drive. | ||
| 101 | + if s.startswith(sep) or s.startswith(colon_sep, 1): | ||
| 102 | + return True | ||
| 103 | + return False | ||
| 100 | 104 | ||
| 101 | 105 | ||
| 102 | 106 | # Join two (or more) paths. | |
@@ -172,34 +176,26 @@ def splitdrive(p): | |||
| 172 | 176 | sep = b'\\' | |
| 173 | 177 | altsep = b'/' | |
| 174 | 178 | colon = b':' | |
| 175 | - unc_prefix = b'\\\\?\\UNC' | ||
| 179 | + unc_prefix = b'\\\\?\\UNC\\' | ||
| 176 | 180 | else: | |
| 177 | 181 | sep = '\\' | |
| 178 | 182 | altsep = '/' | |
| 179 | 183 | colon = ':' | |
| 180 | - unc_prefix = '\\\\?\\UNC' | ||
| 184 | + unc_prefix = '\\\\?\\UNC\\' | ||
| 181 | 185 | normp = p.replace(altsep, sep) | |
| 182 | - if (normp[0:2] == sep*2) and (normp[2:3] != sep): | ||
| 183 | - # is a UNC path: | ||
| 184 | - # vvvvvvvvvvvvvvvvvvvv drive letter or UNC path | ||
| 185 | - # \\machine\mountpoint\directory\etc\... | ||
| 186 | - # directory ^^^^^^^^^^^^^^^ | ||
| 187 | - if normp[:8].upper().rstrip(sep) == unc_prefix: | ||
| 188 | - start = 8 | ||
| 189 | - else: | ||
| 190 | - start = 2 | ||
| 186 | + if normp[0:2] == sep * 2: | ||
| 187 | + # UNC drives, e.g. \\server\share or \\?\UNC\server\share | ||
| 188 | + # Device drives, e.g. \\.\device or \\?\device | ||
| 189 | + start = 8 if normp[:8].upper() == unc_prefix else 2 | ||
| 191 | 190 | index = normp.find(sep, start) | |
| 192 | 191 | if index == -1: | |
| 193 | - return p[:0], p | ||
| 192 | + return p, p[:0] | ||
| 194 | 193 | index2 = normp.find(sep, index + 1) | |
| 195 | - # a UNC path can't have two slashes in a row | ||
| 196 | - # (after the initial two) | ||
| 197 | - if index2 == index + 1: | ||
| 198 | - return p[:0], p | ||
| 199 | 194 | if index2 == -1: | |
| 200 | - index2 = len(p) | ||
| 195 | + return p, p[:0] | ||
| 201 | 196 | return p[:index2], p[index2:] | |
| 202 | 197 | if normp[1:2] == colon: | |
| 198 | + # Drive-letter drives, e.g. X: | ||
| 203 | 199 | return p[:2], p[2:] | |
| 204 | 200 | return p[:0], p | |
| 205 | 201 | ||
@@ -523,20 +519,11 @@ def normpath(path): | |||
| 523 | 519 | altsep = b'/' | |
| 524 | 520 | curdir = b'.' | |
| 525 | 521 | pardir = b'..' | |
| 526 | - special_prefixes = (b'\\\\.\\', b'\\\\?\\') | ||
| 527 | 522 | else: | |
| 528 | 523 | sep = '\\' | |
| 529 | 524 | altsep = '/' | |
| 530 | 525 | curdir = '.' | |
| 531 | 526 | pardir = '..' | |
| 532 | - special_prefixes = ('\\\\.\\', '\\\\?\\') | ||
| 533 | - if path.startswith(special_prefixes): | ||
| 534 | - # in the case of paths with these prefixes: | ||
| 535 | - # \\.\ -> device names | ||
| 536 | - # \\?\ -> literal paths | ||
| 537 | - # do not do any normalization, but return the path | ||
| 538 | - # unchanged apart from the call to os.fspath() | ||
| 539 | - return path | ||
| 540 | 527 | path = path.replace(altsep, sep) | |
| 541 | 528 | prefix, path = splitdrive(path) | |
| 542 | 529 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -107,22 +107,22 @@ def test_splitdrive(self): | |||
| 107 | 107 | tester('ntpath.splitdrive("//conky/mountpoint/foo/bar")', | |
| 108 | 108 | ('//conky/mountpoint', '/foo/bar')) | |
| 109 | 109 | tester('ntpath.splitdrive("\\\\\\conky\\mountpoint\\foo\\bar")', | |
| 110 | - ('', '\\\\\\conky\\mountpoint\\foo\\bar')) | ||
| 110 | + ('\\\\\\conky', '\\mountpoint\\foo\\bar')) | ||
| 111 | 111 | tester('ntpath.splitdrive("///conky/mountpoint/foo/bar")', | |
| 112 | - ('', '///conky/mountpoint/foo/bar')) | ||
| 112 | + ('///conky', '/mountpoint/foo/bar')) | ||
| 113 | 113 | tester('ntpath.splitdrive("\\\\conky\\\\mountpoint\\foo\\bar")', | |
| 114 | - ('', '\\\\conky\\\\mountpoint\\foo\\bar')) | ||
| 114 | + ('\\\\conky\\', '\\mountpoint\\foo\\bar')) | ||
| 115 | 115 | tester('ntpath.splitdrive("//conky//mountpoint/foo/bar")', | |
| 116 | - ('', '//conky//mountpoint/foo/bar')) | ||
| 116 | + ('//conky/', '/mountpoint/foo/bar')) | ||
| 117 | 117 | # Issue #19911: UNC part containing U+0130 | |
| 118 | 118 | self.assertEqual(ntpath.splitdrive('//conky/MOUNTPOİNT/foo/bar'), | |
| 119 | 119 | ('//conky/MOUNTPOİNT', '/foo/bar')) | |
| 120 | 120 | # gh-81790: support device namespace, including UNC drives. | |
| 121 | 121 | tester('ntpath.splitdrive("//?/c:")', ("//?/c:", "")) | |
| 122 | 122 | tester('ntpath.splitdrive("//?/c:/")', ("//?/c:", "/")) | |
| 123 | 123 | tester('ntpath.splitdrive("//?/c:/dir")', ("//?/c:", "/dir")) | |
| 124 | - tester('ntpath.splitdrive("//?/UNC")', ("", "//?/UNC")) | ||
| 125 | - tester('ntpath.splitdrive("//?/UNC/")', ("", "//?/UNC/")) | ||
| 124 | + tester('ntpath.splitdrive("//?/UNC")', ("//?/UNC", "")) | ||
| 125 | + tester('ntpath.splitdrive("//?/UNC/")', ("//?/UNC/", "")) | ||
| 126 | 126 | tester('ntpath.splitdrive("//?/UNC/server/")', ("//?/UNC/server/", "")) | |
| 127 | 127 | tester('ntpath.splitdrive("//?/UNC/server/share")', ("//?/UNC/server/share", "")) | |
| 128 | 128 | tester('ntpath.splitdrive("//?/UNC/server/share/dir")', ("//?/UNC/server/share", "/dir")) | |
@@ -133,8 +133,8 @@ def test_splitdrive(self): | |||
| 133 | 133 | tester('ntpath.splitdrive("\\\\?\\c:")', ("\\\\?\\c:", "")) | |
| 134 | 134 | tester('ntpath.splitdrive("\\\\?\\c:\\")', ("\\\\?\\c:", "\\")) | |
| 135 | 135 | tester('ntpath.splitdrive("\\\\?\\c:\\dir")', ("\\\\?\\c:", "\\dir")) | |
| 136 | - tester('ntpath.splitdrive("\\\\?\\UNC")', ("", "\\\\?\\UNC")) | ||
| 137 | - tester('ntpath.splitdrive("\\\\?\\UNC\\")', ("", "\\\\?\\UNC\\")) | ||
| 136 | + tester('ntpath.splitdrive("\\\\?\\UNC")', ("\\\\?\\UNC", "")) | ||
| 137 | + tester('ntpath.splitdrive("\\\\?\\UNC\\")', ("\\\\?\\UNC\\", "")) | ||
| 138 | 138 | tester('ntpath.splitdrive("\\\\?\\UNC\\server\\")', ("\\\\?\\UNC\\server\\", "")) | |
| 139 | 139 | tester('ntpath.splitdrive("\\\\?\\UNC\\server\\share")', ("\\\\?\\UNC\\server\\share", "")) | |
| 140 | 140 | tester('ntpath.splitdrive("\\\\?\\UNC\\server\\share\\dir")', | |
@@ -143,6 +143,13 @@ def test_splitdrive(self): | |||
| 143 | 143 | ('\\\\?\\VOLUME{00000000-0000-0000-0000-000000000000}', '\\spam')) | |
| 144 | 144 | tester('ntpath.splitdrive("\\\\?\\BootPartition\\")', ("\\\\?\\BootPartition", "\\")) | |
| 145 | 145 | ||
| 146 | + # gh-96290: support partial/invalid UNC drives | ||
| 147 | + tester('ntpath.splitdrive("//")', ("//", "")) # empty server & missing share | ||
| 148 | + tester('ntpath.splitdrive("///")', ("///", "")) # empty server & empty share | ||
| 149 | + tester('ntpath.splitdrive("///y")', ("///y", "")) # empty server & non-empty share | ||
| 150 | + tester('ntpath.splitdrive("//x")', ("//x", "")) # non-empty server & missing share | ||
| 151 | + tester('ntpath.splitdrive("//x/")', ("//x/", "")) # non-empty server & empty share | ||
| 152 | + | ||
| 146 | 153 | def test_split(self): | |
| 147 | 154 | tester('ntpath.split("c:\\foo\\bar")', ('c:\\foo', 'bar')) | |
| 148 | 155 | tester('ntpath.split("\\\\conky\\mountpoint\\foo\\bar")', | |
@@ -161,6 +168,10 @@ def test_isabs(self): | |||
| 161 | 168 | tester('ntpath.isabs("\\foo")', 1) | |
| 162 | 169 | tester('ntpath.isabs("\\foo\\bar")', 1) | |
| 163 | 170 | ||
| 171 | + # gh-96290: normal UNC paths and device paths without trailing backslashes | ||
| 172 | + tester('ntpath.isabs("\\\\conky\\mountpoint")', 1) | ||
| 173 | + tester('ntpath.isabs("\\\\.\\C:")', 1) | ||
| 174 | + | ||
| 164 | 175 | def test_commonprefix(self): | |
| 165 | 176 | tester('ntpath.commonprefix(["/home/swenson/spam", "/home/swen/spam"])', | |
| 166 | 177 | "/home/swen") | |
@@ -270,6 +281,12 @@ def test_normpath(self): | |||
| 270 | 281 | tester("ntpath.normpath('//server/share/../..')", '\\\\server\\share\\') | |
| 271 | 282 | tester("ntpath.normpath('//server/share/../../')", '\\\\server\\share\\') | |
| 272 | 283 | ||
| 284 | + # gh-96290: don't normalize partial/invalid UNC drives as rooted paths. | ||
| 285 | + tester("ntpath.normpath('\\\\foo\\\\')", '\\\\foo\\\\') | ||
| 286 | + tester("ntpath.normpath('\\\\foo\\')", '\\\\foo\\') | ||
| 287 | + tester("ntpath.normpath('\\\\foo')", '\\\\foo') | ||
| 288 | + tester("ntpath.normpath('\\\\')", '\\\\') | ||
| 289 | + | ||
| 273 | 290 | def test_realpath_curdir(self): | |
| 274 | 291 | expected = ntpath.normpath(os.getcwd()) | |
| 275 | 292 | tester("ntpath.realpath('.')", expected) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1469,10 +1469,10 @@ def test_extract_hackers_arcnames_windows_only(self): | |||
| 1469 | 1469 | (r'C:\foo\bar', 'foo/bar'), | |
| 1470 | 1470 | (r'//conky/mountpoint/foo/bar', 'foo/bar'), | |
| 1471 | 1471 | (r'\\conky\mountpoint\foo\bar', 'foo/bar'), | |
| 1472 | - (r'///conky/mountpoint/foo/bar', 'conky/mountpoint/foo/bar'), | ||
| 1473 | - (r'\\\conky\mountpoint\foo\bar', 'conky/mountpoint/foo/bar'), | ||
| 1474 | - (r'//conky//mountpoint/foo/bar', 'conky/mountpoint/foo/bar'), | ||
| 1475 | - (r'\\conky\\mountpoint\foo\bar', 'conky/mountpoint/foo/bar'), | ||
| 1472 | + (r'///conky/mountpoint/foo/bar', 'mountpoint/foo/bar'), | ||
| 1473 | + (r'\\\conky\mountpoint\foo\bar', 'mountpoint/foo/bar'), | ||
| 1474 | + (r'//conky//mountpoint/foo/bar', 'mountpoint/foo/bar'), | ||
| 1475 | + (r'\\conky\\mountpoint\foo\bar', 'mountpoint/foo/bar'), | ||
| 1476 | 1476 | (r'//?/C:/foo/bar', 'foo/bar'), | |
| 1477 | 1477 | (r'\\?\C:\foo\bar', 'foo/bar'), | |
| 1478 | 1478 | (r'C:/../C:/foo/bar', 'C_/foo/bar'), | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,5 @@ | |||
| 1 | + Fix handling of partial and invalid UNC drives in ``ntpath.splitdrive()``, and in | ||
| 2 | + ``ntpath.normpath()`` on non-Windows systems. Paths such as '\\server' and '\\' are now considered | ||
| 3 | + by ``splitdrive()`` to contain only a drive, and consequently are not modified by ``normpath()`` on | ||
| 4 | + non-Windows systems. The behaviour of ``normpath()`` on Windows systems is unaffected, as native | ||
| 5 | + OS APIs are used. Patch by Eryk Sun, with contributions by Barney Gale. | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments