cpython
cpython copied to clipboard
Same interface for `posixpath` & `ntpath`
Feature or enhancement
Proposal:
Five changes:
- Deduplicate code in
split
,basename
&dirname
like inntpath
. - Decouple logic for
splitdrive
fromsplitroot
inntpath
. - Deduplicate
lexists
implementations by defining it ingenericpath
. - Add
posixpath
implementation forisreserved
&isdevdrive
to provide the same interface forposixpath
&ntpath
. - Add
isdevdrive
to__all__
inntpath
.
# ntpath.py
__all__ = ["normcase","isabs","join","splitdrive","splitroot","split","splitext",
"basename","dirname","commonprefix","getsize","getmtime",
"getatime","getctime", "islink","exists","lexists","isdir","isfile",
"ismount","isreserved","expanduser","expandvars","normpath",
"abspath","curdir","pardir","sep","pathsep","defpath","altsep",
"extsep","devnull","realpath","supports_unicode_filenames","relpath",
- "samefile", "sameopenfile", "samestat", "commonpath", "isjunction"]
+ "samefile", "sameopenfile", "samestat", "commonpath", "isjunction",
+ "isdevdrive"]
def splitdrive(p):
"""Split a pathname into drive/UNC sharepoint and relative path specifiers.
"""
- drive, root, tail = splitroot(p)
- return drive, root + tail
+ p = os.fspath(p)
+ if isinstance(p, bytes):
+ sep = b'\\'
+ altsep = b'/'
+ colon = b':'
+ unc_prefix = b'\\\\?\\UNC\\'
+ else:
+ sep = '\\'
+ altsep = '/'
+ colon = ':'
+ unc_prefix = '\\\\?\\UNC\\'
+ normp = p.replace(altsep, sep)
+ if normp[:1] != sep:
+ if normp[1:2] == colon:
+ # Drive-letter drives, e.g. X:
+ return p[:2], p[2:]
+ elif normp[1:2] == sep:
+ # 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, p[:0]
+ index2 = normp.find(sep, index + 1)
+ if index2 == -1:
+ return p, p[:0]
+ return p[:index2], p[index2:]
+ return p[:0], p
def splitroot(p):
"""Split a pathname into drive, root and tail."""
- p = os.fspath(p)
+ drive, p = splitdrive(p)
if isinstance(p, bytes):
sep = b'\\'
altsep = b'/'
- colon = b':'
- unc_prefix = b'\\\\?\\UNC\\'
- empty = b''
else:
sep = '\\'
altsep = '/'
- colon = ':'
- unc_prefix = '\\\\?\\UNC\\'
- empty = ''
normp = p.replace(altsep, sep)
if normp[:1] == sep:
- if normp[1:2] == sep:
- # 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, empty, empty
- index2 = normp.find(sep, index + 1)
- if index2 == -1:
- return p, empty, empty
- return p[:index2], p[index2:index2 + 1], p[index2 + 1:]
- else:
- # Relative path with root, e.g. \Windows
- return empty, p[:1], p[1:]
- elif normp[1:2] == colon:
- if normp[2:3] == sep:
- # Absolute drive-letter path, e.g. X:\Windows
- return p[:2], p[2:3], p[3:]
- else:
- # Relative path with drive, e.g. X:Windows
- return p[:2], empty, p[2:]
- else:
- # Relative path, e.g. Windows
- return empty, empty, p
+ # Absolute path, e.g. X:\Windows
+ return drive, p[:1], p[1:]
+ # Relative path, e.g. X:Windows
+ return drive, p[:0], p
-# Being true for dangling symbolic links is also useful.
-
-def lexists(path):
- """Test whether a path exists. Returns True for broken symbolic links"""
- try:
- st = os.lstat(path)
- except (OSError, ValueError):
- return False
- return True
# posixpath.py
__all__ = ["normcase","isabs","join","splitdrive","splitroot","split","splitext",
"basename","dirname","commonprefix","getsize","getmtime",
"getatime","getctime","islink","exists","lexists","isdir","isfile",
"ismount", "expanduser","expandvars","normpath","abspath",
"samefile","sameopenfile","samestat",
"curdir","pardir","sep","pathsep","defpath","altsep","extsep",
"devnull","realpath","supports_unicode_filenames","relpath",
- "commonpath", "isjunction"]
+ "commonpath", "isjunction","isreserved","isdevdrive"]
def basename(p):
"""Returns the final component of a pathname"""
- p = os.fspath(p)
- sep = _get_sep(p)
- i = p.rfind(sep) + 1
- return p[I:]
+ return split(p)[1]
def dirname(p):
"""Returns the directory component of a pathname"""
- p = os.fspath(p)
- sep = _get_sep(p)
- i = p.rfind(sep) + 1
- head = p[:I]
- if head and head != sep*len(head):
- head = head.rstrip(sep)
- return head
+ return split(p)[0]
-# Being true for dangling symbolic links is also useful.
-
-def lexists(path):
- """Test whether a path exists. Returns True for broken symbolic links"""
- try:
- os.lstat(path)
- except (OSError, ValueError):
- return False
- return True
+def isreserved(path):
+ """Return true if the pathname is reserved by the system.
+ Always returns False on posix"""
+ return False
+
+def isdevdrive(path):
+ """Determines whether the specified path is on a Dev Drive.
+ Dev Drives are not a part of posix semantics"""
+ return False
# genericpath.py
__all__ = ['commonprefix', 'exists', 'getatime', 'getctime', 'getmtime',
'getsize', 'isdir', 'isfile', 'samefile', 'sameopenfile',
- 'samestat']
+ 'samestat', 'lexists']
+# Being true for dangling symbolic links is also useful.
+def lexists(path):
+ """Test whether a path exists. Returns True for broken symbolic links"""
+ try:
+ os.lstat(path)
+ except (OSError, ValueError):
+ return False
Has this already been discussed elsewhere?
This is a minor feature, which does not need previous discussion elsewhere
Links to previous discussion of this feature:
No response
Linked PRs
- gh-117115