diff options
author | AlexSm <[email protected]> | 2024-03-05 10:40:59 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2024-03-05 12:40:59 +0300 |
commit | 1ac13c847b5358faba44dbb638a828e24369467b (patch) | |
tree | 07672b4dd3604ad3dee540a02c6494cb7d10dc3d /contrib/tools/python3/src/Lib/ntpath.py | |
parent | ffcca3e7f7958ddc6487b91d3df8c01054bd0638 (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.py | 897 |
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 |