summaryrefslogtreecommitdiffstats
path: root/Lib/ntpath.py
diff options
context:
space:
mode:
authorBarney Gale <barney.gale@gmail.com>2023-01-12 19:24:57 (GMT)
committerGitHub <noreply@github.com>2023-01-12 19:24:57 (GMT)
commit005e69403d638f9ff8f71e59960c600016e101a4 (patch)
treee91cca78084f6b4efcf56c66162bf45f3d7c4c0e /Lib/ntpath.py
parenteecd422d1ba849f0724962666ba840581217812b (diff)
downloadcpython-005e69403d638f9ff8f71e59960c600016e101a4.zip
cpython-005e69403d638f9ff8f71e59960c600016e101a4.tar.gz
cpython-005e69403d638f9ff8f71e59960c600016e101a4.tar.bz2
gh-96290: Support partial/invalid UNC drives in ntpath.normpath() and splitdrive() (GH-100351)
This brings the Python implementation of `ntpath.normpath()` in line with the C implementation added in 99fcf15 Co-authored-by: Eryk Sun <eryksun@gmail.com>
Diffstat (limited to 'Lib/ntpath.py')
-rw-r--r--Lib/ntpath.py55
1 files changed, 21 insertions, 34 deletions
diff --git a/Lib/ntpath.py b/Lib/ntpath.py
index 265eaa8..cd7fb58 100644
--- a/Lib/ntpath.py
+++ b/Lib/ntpath.py
@@ -87,16 +87,20 @@ except ImportError:
def isabs(s):
"""Test whether a path is absolute"""
s = os.fspath(s)
- # Paths beginning with \\?\ are always absolute, but do not
- # necessarily contain a drive.
if isinstance(s, bytes):
- if s.replace(b'/', b'\\').startswith(b'\\\\?\\'):
- return True
+ sep = b'\\'
+ altsep = b'/'
+ colon_sep = b':\\'
else:
- if s.replace('/', '\\').startswith('\\\\?\\'):
- return True
- s = splitdrive(s)[1]
- return len(s) > 0 and s[0] and s[0] in _get_bothseps(s)
+ sep = '\\'
+ altsep = '/'
+ colon_sep = ':\\'
+ s = s[:3].replace(altsep, sep)
+ # Absolute: UNC, device, and paths with a drive and root.
+ # LEGACY BUG: isabs("/x") should be false since the path has no drive.
+ if s.startswith(sep) or s.startswith(colon_sep, 1):
+ return True
+ return False
# Join two (or more) paths.
@@ -172,34 +176,26 @@ def splitdrive(p):
sep = b'\\'
altsep = b'/'
colon = b':'
- unc_prefix = b'\\\\?\\UNC'
+ unc_prefix = b'\\\\?\\UNC\\'
else:
sep = '\\'
altsep = '/'
colon = ':'
- unc_prefix = '\\\\?\\UNC'
+ unc_prefix = '\\\\?\\UNC\\'
normp = p.replace(altsep, sep)
- if (normp[0:2] == sep*2) and (normp[2:3] != sep):
- # is a UNC path:
- # vvvvvvvvvvvvvvvvvvvv drive letter or UNC path
- # \\machine\mountpoint\directory\etc\...
- # directory ^^^^^^^^^^^^^^^
- if normp[:8].upper().rstrip(sep) == unc_prefix:
- start = 8
- else:
- start = 2
+ if normp[0:2] == sep * 2:
+ # UNC drives, e.g. \\server\share or \\?\UNC\server\share
+ # Device drives, e.g. \\.\device or \\?\device
+ start = 8 if normp[:8].upper() == unc_prefix else 2
index = normp.find(sep, start)
if index == -1:
- return p[:0], p
+ return p, p[:0]
index2 = normp.find(sep, index + 1)
- # a UNC path can't have two slashes in a row
- # (after the initial two)
- if index2 == index + 1:
- return p[:0], p
if index2 == -1:
- index2 = len(p)
+ return p, p[:0]
return p[:index2], p[index2:]
if normp[1:2] == colon:
+ # Drive-letter drives, e.g. X:
return p[:2], p[2:]
return p[:0], p
@@ -523,20 +519,11 @@ except ImportError:
altsep = b'/'
curdir = b'.'
pardir = b'..'
- special_prefixes = (b'\\\\.\\', b'\\\\?\\')
else:
sep = '\\'
altsep = '/'
curdir = '.'
pardir = '..'
- special_prefixes = ('\\\\.\\', '\\\\?\\')
- if path.startswith(special_prefixes):
- # in the case of paths with these prefixes:
- # \\.\ -> device names
- # \\?\ -> literal paths
- # do not do any normalization, but return the path
- # unchanged apart from the call to os.fspath()
- return path
path = path.replace(altsep, sep)
prefix, path = splitdrive(path)