summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Lib/ntpath.py
diff options
context:
space:
mode:
authorAlexSm <[email protected]>2024-03-05 10:40:59 +0100
committerGitHub <[email protected]>2024-03-05 12:40:59 +0300
commit1ac13c847b5358faba44dbb638a828e24369467b (patch)
tree07672b4dd3604ad3dee540a02c6494cb7d10dc3d /contrib/tools/python3/src/Lib/ntpath.py
parentffcca3e7f7958ddc6487b91d3df8c01054bd0638 (diff)
Library import 16 (#2433)
Co-authored-by: robot-piglet <[email protected]> Co-authored-by: deshevoy <[email protected]> Co-authored-by: robot-contrib <[email protected]> Co-authored-by: thegeorg <[email protected]> Co-authored-by: robot-ya-builder <[email protected]> Co-authored-by: svidyuk <[email protected]> Co-authored-by: shadchin <[email protected]> Co-authored-by: robot-ratatosk <[email protected]> Co-authored-by: innokentii <[email protected]> Co-authored-by: arkady-e1ppa <[email protected]> Co-authored-by: snermolaev <[email protected]> Co-authored-by: dimdim11 <[email protected]> Co-authored-by: kickbutt <[email protected]> Co-authored-by: abdullinsaid <[email protected]> Co-authored-by: korsunandrei <[email protected]> Co-authored-by: petrk <[email protected]> Co-authored-by: miroslav2 <[email protected]> Co-authored-by: serjflint <[email protected]> Co-authored-by: akhropov <[email protected]> Co-authored-by: prettyboy <[email protected]> Co-authored-by: ilikepugs <[email protected]> Co-authored-by: hiddenpath <[email protected]> Co-authored-by: mikhnenko <[email protected]> Co-authored-by: spreis <[email protected]> Co-authored-by: andreyshspb <[email protected]> Co-authored-by: dimaandreev <[email protected]> Co-authored-by: rashid <[email protected]> Co-authored-by: robot-ydb-importer <[email protected]> Co-authored-by: r-vetrov <[email protected]> Co-authored-by: ypodlesov <[email protected]> Co-authored-by: zaverden <[email protected]> Co-authored-by: vpozdyayev <[email protected]> Co-authored-by: robot-cozmo <[email protected]> Co-authored-by: v-korovin <[email protected]> Co-authored-by: arikon <[email protected]> Co-authored-by: khoden <[email protected]> Co-authored-by: psydmm <[email protected]> Co-authored-by: robot-javacom <[email protected]> Co-authored-by: dtorilov <[email protected]> Co-authored-by: sennikovmv <[email protected]> Co-authored-by: hcpp <[email protected]>
Diffstat (limited to 'contrib/tools/python3/src/Lib/ntpath.py')
-rw-r--r--contrib/tools/python3/src/Lib/ntpath.py897
1 files changed, 0 insertions, 897 deletions
diff --git a/contrib/tools/python3/src/Lib/ntpath.py b/contrib/tools/python3/src/Lib/ntpath.py
deleted file mode 100644
index df3402d46c9..00000000000
--- a/contrib/tools/python3/src/Lib/ntpath.py
+++ /dev/null
@@ -1,897 +0,0 @@
-# Module 'ntpath' -- common operations on WinNT/Win95 pathnames
-"""Common pathname manipulations, WindowsNT/95 version.
-
-Instead of importing this module directly, import os and refer to this
-module as os.path.
-"""
-
-# strings representing various path-related bits and pieces
-# These are primarily for export; internally, they are hardcoded.
-# Should be set before imports for resolving cyclic dependency.
-curdir = '.'
-pardir = '..'
-extsep = '.'
-sep = '\\'
-pathsep = ';'
-altsep = '/'
-defpath = '.;C:\\bin'
-devnull = 'nul'
-
-import os
-import sys
-import stat
-import genericpath
-from genericpath import *
-
-
-__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",
- "curdir","pardir","sep","pathsep","defpath","altsep",
- "extsep","devnull","realpath","supports_unicode_filenames","relpath",
- "samefile", "sameopenfile", "samestat", "commonpath", "isjunction"]
-
-def _get_bothseps(path):
- if isinstance(path, bytes):
- return b'\\/'
- else:
- return '\\/'
-
-# Normalize the case of a pathname and map slashes to backslashes.
-# Other normalizations (such as optimizing '../' away) are not done
-# (this is done by normpath).
-
-try:
- from _winapi import (
- LCMapStringEx as _LCMapStringEx,
- LOCALE_NAME_INVARIANT as _LOCALE_NAME_INVARIANT,
- LCMAP_LOWERCASE as _LCMAP_LOWERCASE)
-
- def normcase(s):
- """Normalize case of pathname.
-
- Makes all characters lowercase and all slashes into backslashes.
- """
- s = os.fspath(s)
- if not s:
- return s
- if isinstance(s, bytes):
- encoding = sys.getfilesystemencoding()
- s = s.decode(encoding, 'surrogateescape').replace('/', '\\')
- s = _LCMapStringEx(_LOCALE_NAME_INVARIANT,
- _LCMAP_LOWERCASE, s)
- return s.encode(encoding, 'surrogateescape')
- else:
- return _LCMapStringEx(_LOCALE_NAME_INVARIANT,
- _LCMAP_LOWERCASE,
- s.replace('/', '\\'))
-except ImportError:
- def normcase(s):
- """Normalize case of pathname.
-
- Makes all characters lowercase and all slashes into backslashes.
- """
- s = os.fspath(s)
- if isinstance(s, bytes):
- return os.fsencode(os.fsdecode(s).replace('/', '\\').lower())
- return s.replace('/', '\\').lower()
-
-
-# Return whether a path is absolute.
-# Trivial in Posix, harder on Windows.
-# For Windows it is absolute if it starts with a slash or backslash (current
-# volume), or if a pathname after the volume-letter-and-colon or UNC-resource
-# starts with a slash or backslash.
-
-def isabs(s):
- """Test whether a path is absolute"""
- s = os.fspath(s)
- if isinstance(s, bytes):
- sep = b'\\'
- altsep = b'/'
- colon_sep = b':\\'
- else:
- 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.
-def join(path, *paths):
- path = os.fspath(path)
- if isinstance(path, bytes):
- sep = b'\\'
- seps = b'\\/'
- colon = b':'
- else:
- sep = '\\'
- seps = '\\/'
- colon = ':'
- try:
- if not paths:
- path[:0] + sep #23780: Ensure compatible data type even if p is null.
- result_drive, result_root, result_path = splitroot(path)
- for p in map(os.fspath, paths):
- p_drive, p_root, p_path = splitroot(p)
- if p_root:
- # Second path is absolute
- if p_drive or not result_drive:
- result_drive = p_drive
- result_root = p_root
- result_path = p_path
- continue
- elif p_drive and p_drive != result_drive:
- if p_drive.lower() != result_drive.lower():
- # Different drives => ignore the first path entirely
- result_drive = p_drive
- result_root = p_root
- result_path = p_path
- continue
- # Same drive in different case
- result_drive = p_drive
- # Second path is relative to the first
- if result_path and result_path[-1] not in seps:
- result_path = result_path + sep
- result_path = result_path + p_path
- ## add separator between UNC and non-absolute path
- if (result_path and not result_root and
- result_drive and result_drive[-1:] not in colon + seps):
- return result_drive + sep + result_path
- return result_drive + result_root + result_path
- except (TypeError, AttributeError, BytesWarning):
- genericpath._check_arg_types('join', path, *paths)
- raise
-
-
-# Split a path in a drive specification (a drive letter followed by a
-# colon) and the path specification.
-# It is always true that drivespec + pathspec == p
-def splitdrive(p):
- """Split a pathname into drive/UNC sharepoint and relative path specifiers.
- Returns a 2-tuple (drive_or_unc, path); either part may be empty.
-
- If you assign
- result = splitdrive(p)
- It is always true that:
- result[0] + result[1] == p
-
- If the path contained a drive letter, drive_or_unc will contain everything
- up to and including the colon. e.g. splitdrive("c:/dir") returns ("c:", "/dir")
-
- If the path contained a UNC path, the drive_or_unc will contain the host name
- and share up to but not including the fourth directory separator character.
- e.g. splitdrive("//host/computer/dir") returns ("//host/computer", "/dir")
-
- Paths cannot contain both a drive letter and a UNC path.
-
- """
- drive, root, tail = splitroot(p)
- return drive, root + tail
-
-
-def splitroot(p):
- """Split a pathname into drive, root and tail. The drive is defined
- exactly as in splitdrive(). On Windows, the root may be a single path
- separator or an empty string. The tail contains anything after the root.
- For example:
-
- splitroot('//server/share/') == ('//server/share', '/', '')
- splitroot('C:/Users/Barney') == ('C:', '/', 'Users/Barney')
- splitroot('C:///spam///ham') == ('C:', '/', '//spam///ham')
- splitroot('Windows/notepad') == ('', '', 'Windows/notepad')
- """
- p = os.fspath(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
-
-
-# Split a path in head (everything up to the last '/') and tail (the
-# rest). After the trailing '/' is stripped, the invariant
-# join(head, tail) == p holds.
-# The resulting head won't end in '/' unless it is the root.
-
-def split(p):
- """Split a pathname.
-
- Return tuple (head, tail) where tail is everything after the final slash.
- Either part may be empty."""
- p = os.fspath(p)
- seps = _get_bothseps(p)
- d, r, p = splitroot(p)
- # set i to index beyond p's last slash
- i = len(p)
- while i and p[i-1] not in seps:
- i -= 1
- head, tail = p[:i], p[i:] # now tail has no slashes
- return d + r + head.rstrip(seps), tail
-
-
-# Split a path in root and extension.
-# The extension is everything starting at the last dot in the last
-# pathname component; the root is everything before that.
-# It is always true that root + ext == p.
-
-def splitext(p):
- p = os.fspath(p)
- if isinstance(p, bytes):
- return genericpath._splitext(p, b'\\', b'/', b'.')
- else:
- return genericpath._splitext(p, '\\', '/', '.')
-splitext.__doc__ = genericpath._splitext.__doc__
-
-
-# Return the tail (basename) part of a path.
-
-def basename(p):
- """Returns the final component of a pathname"""
- return split(p)[1]
-
-
-# Return the head (dirname) part of a path.
-
-def dirname(p):
- """Returns the directory component of a pathname"""
- return split(p)[0]
-
-
-# Is a path a junction?
-
-if hasattr(os.stat_result, 'st_reparse_tag'):
- def isjunction(path):
- """Test whether a path is a junction"""
- try:
- st = os.lstat(path)
- except (OSError, ValueError, AttributeError):
- return False
- return bool(st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT)
-else:
- def isjunction(path):
- """Test whether a path is a junction"""
- os.fspath(path)
- return False
-
-
-# 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
-
-# Is a path a mount point?
-# Any drive letter root (eg c:\)
-# Any share UNC (eg \\server\share)
-# Any volume mounted on a filesystem folder
-#
-# No one method detects all three situations. Historically we've lexically
-# detected drive letter roots and share UNCs. The canonical approach to
-# detecting mounted volumes (querying the reparse tag) fails for the most
-# common case: drive letter roots. The alternative which uses GetVolumePathName
-# fails if the drive letter is the result of a SUBST.
-try:
- from nt import _getvolumepathname
-except ImportError:
- _getvolumepathname = None
-def ismount(path):
- """Test whether a path is a mount point (a drive root, the root of a
- share, or a mounted volume)"""
- path = os.fspath(path)
- seps = _get_bothseps(path)
- path = abspath(path)
- drive, root, rest = splitroot(path)
- if drive and drive[0] in seps:
- return not rest
- if root and not rest:
- return True
-
- if _getvolumepathname:
- x = path.rstrip(seps)
- y =_getvolumepathname(path).rstrip(seps)
- return x.casefold() == y.casefold()
- else:
- return False
-
-
-# Expand paths beginning with '~' or '~user'.
-# '~' means $HOME; '~user' means that user's home directory.
-# If the path doesn't begin with '~', or if the user or $HOME is unknown,
-# the path is returned unchanged (leaving error reporting to whatever
-# function is called with the expanded path as argument).
-# See also module 'glob' for expansion of *, ? and [...] in pathnames.
-# (A function should also be defined to do full *sh-style environment
-# variable expansion.)
-
-def expanduser(path):
- """Expand ~ and ~user constructs.
-
- If user or $HOME is unknown, do nothing."""
- path = os.fspath(path)
- if isinstance(path, bytes):
- tilde = b'~'
- else:
- tilde = '~'
- if not path.startswith(tilde):
- return path
- i, n = 1, len(path)
- while i < n and path[i] not in _get_bothseps(path):
- i += 1
-
- if 'USERPROFILE' in os.environ:
- userhome = os.environ['USERPROFILE']
- elif not 'HOMEPATH' in os.environ:
- return path
- else:
- try:
- drive = os.environ['HOMEDRIVE']
- except KeyError:
- drive = ''
- userhome = join(drive, os.environ['HOMEPATH'])
-
- if i != 1: #~user
- target_user = path[1:i]
- if isinstance(target_user, bytes):
- target_user = os.fsdecode(target_user)
- current_user = os.environ.get('USERNAME')
-
- if target_user != current_user:
- # Try to guess user home directory. By default all user
- # profile directories are located in the same place and are
- # named by corresponding usernames. If userhome isn't a
- # normal profile directory, this guess is likely wrong,
- # so we bail out.
- if current_user != basename(userhome):
- return path
- userhome = join(dirname(userhome), target_user)
-
- if isinstance(path, bytes):
- userhome = os.fsencode(userhome)
-
- return userhome + path[i:]
-
-
-# Expand paths containing shell variable substitutions.
-# The following rules apply:
-# - no expansion within single quotes
-# - '$$' is translated into '$'
-# - '%%' is translated into '%' if '%%' are not seen in %var1%%var2%
-# - ${varname} is accepted.
-# - $varname is accepted.
-# - %varname% is accepted.
-# - varnames can be made out of letters, digits and the characters '_-'
-# (though is not verified in the ${varname} and %varname% cases)
-# XXX With COMMAND.COM you can use any characters in a variable name,
-# XXX except '^|<>='.
-
-def expandvars(path):
- """Expand shell variables of the forms $var, ${var} and %var%.
-
- Unknown variables are left unchanged."""
- path = os.fspath(path)
- if isinstance(path, bytes):
- if b'$' not in path and b'%' not in path:
- return path
- import string
- varchars = bytes(string.ascii_letters + string.digits + '_-', 'ascii')
- quote = b'\''
- percent = b'%'
- brace = b'{'
- rbrace = b'}'
- dollar = b'$'
- environ = getattr(os, 'environb', None)
- else:
- if '$' not in path and '%' not in path:
- return path
- import string
- varchars = string.ascii_letters + string.digits + '_-'
- quote = '\''
- percent = '%'
- brace = '{'
- rbrace = '}'
- dollar = '$'
- environ = os.environ
- res = path[:0]
- index = 0
- pathlen = len(path)
- while index < pathlen:
- c = path[index:index+1]
- if c == quote: # no expansion within single quotes
- path = path[index + 1:]
- pathlen = len(path)
- try:
- index = path.index(c)
- res += c + path[:index + 1]
- except ValueError:
- res += c + path
- index = pathlen - 1
- elif c == percent: # variable or '%'
- if path[index + 1:index + 2] == percent:
- res += c
- index += 1
- else:
- path = path[index+1:]
- pathlen = len(path)
- try:
- index = path.index(percent)
- except ValueError:
- res += percent + path
- index = pathlen - 1
- else:
- var = path[:index]
- try:
- if environ is None:
- value = os.fsencode(os.environ[os.fsdecode(var)])
- else:
- value = environ[var]
- except KeyError:
- value = percent + var + percent
- res += value
- elif c == dollar: # variable or '$$'
- if path[index + 1:index + 2] == dollar:
- res += c
- index += 1
- elif path[index + 1:index + 2] == brace:
- path = path[index+2:]
- pathlen = len(path)
- try:
- index = path.index(rbrace)
- except ValueError:
- res += dollar + brace + path
- index = pathlen - 1
- else:
- var = path[:index]
- try:
- if environ is None:
- value = os.fsencode(os.environ[os.fsdecode(var)])
- else:
- value = environ[var]
- except KeyError:
- value = dollar + brace + var + rbrace
- res += value
- else:
- var = path[:0]
- index += 1
- c = path[index:index + 1]
- while c and c in varchars:
- var += c
- index += 1
- c = path[index:index + 1]
- try:
- if environ is None:
- value = os.fsencode(os.environ[os.fsdecode(var)])
- else:
- value = environ[var]
- except KeyError:
- value = dollar + var
- res += value
- if c:
- index -= 1
- else:
- res += c
- index += 1
- return res
-
-
-# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B.
-# Previously, this function also truncated pathnames to 8+3 format,
-# but as this module is called "ntpath", that's obviously wrong!
-try:
- from nt import _path_normpath
-
-except ImportError:
- def normpath(path):
- """Normalize path, eliminating double slashes, etc."""
- path = os.fspath(path)
- if isinstance(path, bytes):
- sep = b'\\'
- altsep = b'/'
- curdir = b'.'
- pardir = b'..'
- else:
- sep = '\\'
- altsep = '/'
- curdir = '.'
- pardir = '..'
- path = path.replace(altsep, sep)
- drive, root, path = splitroot(path)
- prefix = drive + root
- comps = path.split(sep)
- i = 0
- while i < len(comps):
- if not comps[i] or comps[i] == curdir:
- del comps[i]
- elif comps[i] == pardir:
- if i > 0 and comps[i-1] != pardir:
- del comps[i-1:i+1]
- i -= 1
- elif i == 0 and root:
- del comps[i]
- else:
- i += 1
- else:
- i += 1
- # If the path is now empty, substitute '.'
- if not prefix and not comps:
- comps.append(curdir)
- return prefix + sep.join(comps)
-
-else:
- def normpath(path):
- """Normalize path, eliminating double slashes, etc."""
- path = os.fspath(path)
- if isinstance(path, bytes):
- return os.fsencode(_path_normpath(os.fsdecode(path))) or b"."
- return _path_normpath(path) or "."
-
-
-def _abspath_fallback(path):
- """Return the absolute version of a path as a fallback function in case
- `nt._getfullpathname` is not available or raises OSError. See bpo-31047 for
- more.
-
- """
-
- path = os.fspath(path)
- if not isabs(path):
- if isinstance(path, bytes):
- cwd = os.getcwdb()
- else:
- cwd = os.getcwd()
- path = join(cwd, path)
- return normpath(path)
-
-# Return an absolute path.
-try:
- from nt import _getfullpathname
-
-except ImportError: # not running on Windows - mock up something sensible
- abspath = _abspath_fallback
-
-else: # use native Windows method on Windows
- def abspath(path):
- """Return the absolute version of a path."""
- try:
- return _getfullpathname(normpath(path))
- except (OSError, ValueError):
- return _abspath_fallback(path)
-
-try:
- from nt import _getfinalpathname, readlink as _nt_readlink
-except ImportError:
- # realpath is a no-op on systems without _getfinalpathname support.
- realpath = abspath
-else:
- def _readlink_deep(path):
- # These error codes indicate that we should stop reading links and
- # return the path we currently have.
- # 1: ERROR_INVALID_FUNCTION
- # 2: ERROR_FILE_NOT_FOUND
- # 3: ERROR_DIRECTORY_NOT_FOUND
- # 5: ERROR_ACCESS_DENIED
- # 21: ERROR_NOT_READY (implies drive with no media)
- # 32: ERROR_SHARING_VIOLATION (probably an NTFS paging file)
- # 50: ERROR_NOT_SUPPORTED (implies no support for reparse points)
- # 67: ERROR_BAD_NET_NAME (implies remote server unavailable)
- # 87: ERROR_INVALID_PARAMETER
- # 4390: ERROR_NOT_A_REPARSE_POINT
- # 4392: ERROR_INVALID_REPARSE_DATA
- # 4393: ERROR_REPARSE_TAG_INVALID
- allowed_winerror = 1, 2, 3, 5, 21, 32, 50, 67, 87, 4390, 4392, 4393
-
- seen = set()
- while normcase(path) not in seen:
- seen.add(normcase(path))
- try:
- old_path = path
- path = _nt_readlink(path)
- # Links may be relative, so resolve them against their
- # own location
- if not isabs(path):
- # If it's something other than a symlink, we don't know
- # what it's actually going to be resolved against, so
- # just return the old path.
- if not islink(old_path):
- path = old_path
- break
- path = normpath(join(dirname(old_path), path))
- except OSError as ex:
- if ex.winerror in allowed_winerror:
- break
- raise
- except ValueError:
- # Stop on reparse points that are not symlinks
- break
- return path
-
- def _getfinalpathname_nonstrict(path):
- # These error codes indicate that we should stop resolving the path
- # and return the value we currently have.
- # 1: ERROR_INVALID_FUNCTION
- # 2: ERROR_FILE_NOT_FOUND
- # 3: ERROR_DIRECTORY_NOT_FOUND
- # 5: ERROR_ACCESS_DENIED
- # 21: ERROR_NOT_READY (implies drive with no media)
- # 32: ERROR_SHARING_VIOLATION (probably an NTFS paging file)
- # 50: ERROR_NOT_SUPPORTED
- # 53: ERROR_BAD_NETPATH
- # 65: ERROR_NETWORK_ACCESS_DENIED
- # 67: ERROR_BAD_NET_NAME (implies remote server unavailable)
- # 87: ERROR_INVALID_PARAMETER
- # 123: ERROR_INVALID_NAME
- # 161: ERROR_BAD_PATHNAME
- # 1920: ERROR_CANT_ACCESS_FILE
- # 1921: ERROR_CANT_RESOLVE_FILENAME (implies unfollowable symlink)
- allowed_winerror = 1, 2, 3, 5, 21, 32, 50, 53, 65, 67, 87, 123, 161, 1920, 1921
-
- # Non-strict algorithm is to find as much of the target directory
- # as we can and join the rest.
- tail = path[:0]
- while path:
- try:
- path = _getfinalpathname(path)
- return join(path, tail) if tail else path
- except OSError as ex:
- if ex.winerror not in allowed_winerror:
- raise
- try:
- # The OS could not resolve this path fully, so we attempt
- # to follow the link ourselves. If we succeed, join the tail
- # and return.
- new_path = _readlink_deep(path)
- if new_path != path:
- return join(new_path, tail) if tail else new_path
- except OSError:
- # If we fail to readlink(), let's keep traversing
- pass
- path, name = split(path)
- # TODO (bpo-38186): Request the real file name from the directory
- # entry using FindFirstFileW. For now, we will return the path
- # as best we have it
- if path and not name:
- return path + tail
- tail = join(name, tail) if tail else name
- return tail
-
- def realpath(path, *, strict=False):
- path = normpath(path)
- if isinstance(path, bytes):
- prefix = b'\\\\?\\'
- unc_prefix = b'\\\\?\\UNC\\'
- new_unc_prefix = b'\\\\'
- cwd = os.getcwdb()
- # bpo-38081: Special case for realpath(b'nul')
- if normcase(path) == normcase(os.fsencode(devnull)):
- return b'\\\\.\\NUL'
- else:
- prefix = '\\\\?\\'
- unc_prefix = '\\\\?\\UNC\\'
- new_unc_prefix = '\\\\'
- cwd = os.getcwd()
- # bpo-38081: Special case for realpath('nul')
- if normcase(path) == normcase(devnull):
- return '\\\\.\\NUL'
- had_prefix = path.startswith(prefix)
- if not had_prefix and not isabs(path):
- path = join(cwd, path)
- try:
- path = _getfinalpathname(path)
- initial_winerror = 0
- except ValueError as ex:
- # gh-106242: Raised for embedded null characters
- # In strict mode, we convert into an OSError.
- # Non-strict mode returns the path as-is, since we've already
- # made it absolute.
- if strict:
- raise OSError(str(ex)) from None
- path = normpath(path)
- except OSError as ex:
- if strict:
- raise
- initial_winerror = ex.winerror
- path = _getfinalpathname_nonstrict(path)
- # The path returned by _getfinalpathname will always start with \\?\ -
- # strip off that prefix unless it was already provided on the original
- # path.
- if not had_prefix and path.startswith(prefix):
- # For UNC paths, the prefix will actually be \\?\UNC\
- # Handle that case as well.
- if path.startswith(unc_prefix):
- spath = new_unc_prefix + path[len(unc_prefix):]
- else:
- spath = path[len(prefix):]
- # Ensure that the non-prefixed path resolves to the same path
- try:
- if _getfinalpathname(spath) == path:
- path = spath
- except ValueError as ex:
- # Unexpected, as an invalid path should not have gained a prefix
- # at any point, but we ignore this error just in case.
- pass
- except OSError as ex:
- # If the path does not exist and originally did not exist, then
- # strip the prefix anyway.
- if ex.winerror == initial_winerror:
- path = spath
- return path
-
-
-# All supported version have Unicode filename support.
-supports_unicode_filenames = True
-
-def relpath(path, start=None):
- """Return a relative version of a path"""
- path = os.fspath(path)
- if isinstance(path, bytes):
- sep = b'\\'
- curdir = b'.'
- pardir = b'..'
- else:
- sep = '\\'
- curdir = '.'
- pardir = '..'
-
- if start is None:
- start = curdir
-
- if not path:
- raise ValueError("no path specified")
-
- start = os.fspath(start)
- try:
- start_abs = abspath(normpath(start))
- path_abs = abspath(normpath(path))
- start_drive, _, start_rest = splitroot(start_abs)
- path_drive, _, path_rest = splitroot(path_abs)
- if normcase(start_drive) != normcase(path_drive):
- raise ValueError("path is on mount %r, start on mount %r" % (
- path_drive, start_drive))
-
- start_list = [x for x in start_rest.split(sep) if x]
- path_list = [x for x in path_rest.split(sep) if x]
- # Work out how much of the filepath is shared by start and path.
- i = 0
- for e1, e2 in zip(start_list, path_list):
- if normcase(e1) != normcase(e2):
- break
- i += 1
-
- rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
- if not rel_list:
- return curdir
- return join(*rel_list)
- except (TypeError, ValueError, AttributeError, BytesWarning, DeprecationWarning):
- genericpath._check_arg_types('relpath', path, start)
- raise
-
-
-# Return the longest common sub-path of the sequence of paths given as input.
-# The function is case-insensitive and 'separator-insensitive', i.e. if the
-# only difference between two paths is the use of '\' versus '/' as separator,
-# they are deemed to be equal.
-#
-# However, the returned path will have the standard '\' separator (even if the
-# given paths had the alternative '/' separator) and will have the case of the
-# first path given in the sequence. Additionally, any trailing separator is
-# stripped from the returned path.
-
-def commonpath(paths):
- """Given a sequence of path names, returns the longest common sub-path."""
-
- if not paths:
- raise ValueError('commonpath() arg is an empty sequence')
-
- paths = tuple(map(os.fspath, paths))
- if isinstance(paths[0], bytes):
- sep = b'\\'
- altsep = b'/'
- curdir = b'.'
- else:
- sep = '\\'
- altsep = '/'
- curdir = '.'
-
- try:
- drivesplits = [splitroot(p.replace(altsep, sep).lower()) for p in paths]
- split_paths = [p.split(sep) for d, r, p in drivesplits]
-
- if len({r for d, r, p in drivesplits}) != 1:
- raise ValueError("Can't mix absolute and relative paths")
-
- # Check that all drive letters or UNC paths match. The check is made only
- # now otherwise type errors for mixing strings and bytes would not be
- # caught.
- if len({d for d, r, p in drivesplits}) != 1:
- raise ValueError("Paths don't have the same drive")
-
- drive, root, path = splitroot(paths[0].replace(altsep, sep))
- common = path.split(sep)
- common = [c for c in common if c and c != curdir]
-
- split_paths = [[c for c in s if c and c != curdir] for s in split_paths]
- s1 = min(split_paths)
- s2 = max(split_paths)
- for i, c in enumerate(s1):
- if c != s2[i]:
- common = common[:i]
- break
- else:
- common = common[:len(s1)]
-
- return drive + root + sep.join(common)
- except (TypeError, AttributeError):
- genericpath._check_arg_types('commonpath', *paths)
- raise
-
-
-try:
- # The isdir(), isfile(), islink() and exists() implementations in
- # genericpath use os.stat(). This is overkill on Windows. Use simpler
- # builtin functions if they are available.
- from nt import _path_isdir as isdir
- from nt import _path_isfile as isfile
- from nt import _path_islink as islink
- from nt import _path_exists as exists
-except ImportError:
- # Use genericpath.* as imported above
- pass
-
-
-try:
- from nt import _path_isdevdrive
-except ImportError:
- def isdevdrive(path):
- """Determines whether the specified path is on a Windows Dev Drive."""
- # Never a Dev Drive
- return False
-else:
- def isdevdrive(path):
- """Determines whether the specified path is on a Windows Dev Drive."""
- try:
- return _path_isdevdrive(abspath(path))
- except OSError:
- return False