123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680 |
- """Common pathname manipulations, WindowsNT/95 version.
- Instead of importing this module directly, import os and refer to this
- module as os.path.
- """
- import os
- import sys
- import stat
- import genericpath
- from genericpath import *
- __all__ = ["normcase","isabs","join","splitdrive","split","splitext",
- "basename","dirname","commonprefix","getsize","getmtime",
- "getatime","getctime", "islink","exists","lexists","isdir","isfile",
- "ismount", "expanduser","expandvars","normpath","abspath",
- "splitunc","curdir","pardir","sep","pathsep","defpath","altsep",
- "extsep","devnull","realpath","supports_unicode_filenames","relpath",
- "samefile", "sameopenfile", "samestat", "commonpath"]
- curdir = '.'
- pardir = '..'
- extsep = '.'
- sep = '\\'
- pathsep = ';'
- altsep = '/'
- defpath = '.;C:\\bin'
- if 'ce' in sys.builtin_module_names:
- defpath = '\\Windows'
- devnull = 'nul'
- def _get_bothseps(path):
- if isinstance(path, bytes):
- return b'\\/'
- else:
- return '\\/'
- def normcase(s):
- """Normalize case of pathname.
- Makes all characters lowercase and all slashes into backslashes."""
- try:
- if isinstance(s, bytes):
- return s.replace(b'/', b'\\').lower()
- else:
- return s.replace('/', '\\').lower()
- except (TypeError, AttributeError):
- if not isinstance(s, (bytes, str)):
- raise TypeError("normcase() argument must be str or bytes, "
- "not %r" % s.__class__.__name__) from None
- raise
- def isabs(s):
- """Test whether a path is absolute"""
- s = splitdrive(s)[1]
- return len(s) > 0 and s[0] in _get_bothseps(s)
- def join(path, *paths):
- if isinstance(path, bytes):
- sep = b'\\'
- seps = b'\\/'
- colon = b':'
- else:
- sep = '\\'
- seps = '\\/'
- colon = ':'
- try:
- if not paths:
- path[:0] + sep
- result_drive, result_path = splitdrive(path)
- for p in paths:
- p_drive, p_path = splitdrive(p)
- if p_path and p_path[0] in seps:
-
- if p_drive or not result_drive:
- result_drive = p_drive
- result_path = p_path
- continue
- elif p_drive and p_drive != result_drive:
- if p_drive.lower() != result_drive.lower():
-
- result_drive = p_drive
- result_path = p_path
- continue
-
- result_drive = p_drive
-
- if result_path and result_path[-1] not in seps:
- result_path = result_path + sep
- result_path = result_path + p_path
-
- if (result_path and result_path[0] not in seps and
- result_drive and result_drive[-1:] != colon):
- return result_drive + sep + result_path
- return result_drive + result_path
- except (TypeError, AttributeError, BytesWarning):
- genericpath._check_arg_types('join', path, *paths)
- raise
- 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.
- """
- if len(p) >= 2:
- if isinstance(p, bytes):
- sep = b'\\'
- altsep = b'/'
- colon = b':'
- else:
- sep = '\\'
- altsep = '/'
- colon = ':'
- normp = p.replace(altsep, sep)
- if (normp[0:2] == sep*2) and (normp[2:3] != sep):
-
-
-
-
- index = normp.find(sep, 2)
- if index == -1:
- return p[:0], p
- index2 = normp.find(sep, index + 1)
-
-
- if index2 == index + 1:
- return p[:0], p
- if index2 == -1:
- index2 = len(p)
- return p[:index2], p[index2:]
- if normp[1:2] == colon:
- return p[:2], p[2:]
- return p[:0], p
- def splitunc(p):
- """Deprecated since Python 3.1. Please use splitdrive() instead;
- it now handles UNC paths.
- Split a pathname into UNC mount point and relative path specifiers.
- Return a 2-tuple (unc, rest); either part may be empty.
- If unc is not empty, it has the form '//host/mount' (or similar
- using backslashes). unc+rest is always the input path.
- Paths containing drive letters never have a UNC part.
- """
- import warnings
- warnings.warn("ntpath.splitunc is deprecated, use ntpath.splitdrive instead",
- DeprecationWarning, 2)
- drive, path = splitdrive(p)
- if len(drive) == 2:
-
- return p[:0], p
- return drive, path
- def split(p):
- """Split a pathname.
- Return tuple (head, tail) where tail is everything after the final slash.
- Either part may be empty."""
- seps = _get_bothseps(p)
- d, p = splitdrive(p)
-
- i = len(p)
- while i and p[i-1] not in seps:
- i -= 1
- head, tail = p[:i], p[i:]
-
- head = head.rstrip(seps) or head
- return d + head, tail
- def splitext(p):
- if isinstance(p, bytes):
- return genericpath._splitext(p, b'\\', b'/', b'.')
- else:
- return genericpath._splitext(p, '\\', '/', '.')
- splitext.__doc__ = genericpath._splitext.__doc__
- def basename(p):
- """Returns the final component of a pathname"""
- return split(p)[1]
- def dirname(p):
- """Returns the directory component of a pathname"""
- return split(p)[0]
- def islink(path):
- """Test whether a path is a symbolic link.
- This will always return false for Windows prior to 6.0.
- """
- try:
- st = os.lstat(path)
- except (OSError, AttributeError):
- return False
- return stat.S_ISLNK(st.st_mode)
- def lexists(path):
- """Test whether a path exists. Returns True for broken symbolic links"""
- try:
- st = os.lstat(path)
- except OSError:
- return False
- return True
- 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)"""
- seps = _get_bothseps(path)
- path = abspath(path)
- root, rest = splitdrive(path)
- if root and root[0] in seps:
- return (not rest) or (rest in seps)
- if rest in seps:
- return True
- if _getvolumepathname:
- return path.rstrip(seps) == _getvolumepathname(path).rstrip(seps)
- else:
- return False
- def expanduser(path):
- """Expand ~ and ~user constructs.
- If user or $HOME is unknown, do nothing."""
- 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 'HOME' in os.environ:
- userhome = os.environ['HOME']
- elif '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 isinstance(path, bytes):
- userhome = os.fsencode(userhome)
- if i != 1:
- userhome = join(dirname(userhome), path[1:i])
- return userhome + path[i:]
- def expandvars(path):
- """Expand shell variables of the forms $var, ${var} and %var%.
- Unknown variables are left unchanged."""
- 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:
- 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:
- 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:
- 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
- def normpath(path):
- """Normalize path, eliminating double slashes, etc."""
- if isinstance(path, bytes):
- sep = b'\\'
- altsep = b'/'
- curdir = b'.'
- pardir = b'..'
- special_prefixes = (b'\\\\.\\', b'\\\\?\\')
- else:
- sep = '\\'
- altsep = '/'
- curdir = '.'
- pardir = '..'
- special_prefixes = ('\\\\.\\', '\\\\?\\')
- if path.startswith(special_prefixes):
-
-
-
-
- return path
- path = path.replace(altsep, sep)
- prefix, path = splitdrive(path)
-
- if path.startswith(sep):
- prefix += sep
- path = path.lstrip(sep)
- 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 prefix.endswith(sep):
- del comps[i]
- else:
- i += 1
- else:
- i += 1
-
- if not prefix and not comps:
- comps.append(curdir)
- return prefix + sep.join(comps)
- try:
- from nt import _getfullpathname
- except ImportError:
- def abspath(path):
- """Return the absolute version of a path."""
- if not isabs(path):
- if isinstance(path, bytes):
- cwd = os.getcwdb()
- else:
- cwd = os.getcwd()
- path = join(cwd, path)
- return normpath(path)
- else:
- def abspath(path):
- """Return the absolute version of a path."""
- if path:
- try:
- path = _getfullpathname(path)
- except OSError:
- pass
- elif isinstance(path, bytes):
- path = os.getcwdb()
- else:
- path = os.getcwd()
- return normpath(path)
- realpath = abspath
- supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and
- sys.getwindowsversion()[3] >= 2)
- def relpath(path, start=None):
- """Return a relative version of a 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")
- try:
- start_abs = abspath(normpath(start))
- path_abs = abspath(normpath(path))
- start_drive, start_rest = splitdrive(start_abs)
- path_drive, path_rest = splitdrive(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]
-
- 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
- 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')
- if isinstance(paths[0], bytes):
- sep = b'\\'
- altsep = b'/'
- curdir = b'.'
- else:
- sep = '\\'
- altsep = '/'
- curdir = '.'
- try:
- drivesplits = [splitdrive(p.replace(altsep, sep).lower()) for p in paths]
- split_paths = [p.split(sep) for d, p in drivesplits]
- try:
- isabs, = set(p[:1] == sep for d, p in drivesplits)
- except ValueError:
- raise ValueError("Can't mix absolute and relative paths") from None
-
-
-
- if len(set(d for d, p in drivesplits)) != 1:
- raise ValueError("Paths don't have the same drive")
- drive, path = splitdrive(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)]
- prefix = drive + sep if isabs else drive
- return prefix + sep.join(common)
- except (TypeError, AttributeError):
- genericpath._check_arg_types('commonpath', *paths)
- raise
- try:
-
-
- if sys.getwindowsversion()[:2] >= (6, 0):
- from nt import _getfinalpathname
- else:
- raise ImportError
- except (AttributeError, ImportError):
-
-
-
-
- def _getfinalpathname(f):
- return normcase(abspath(f))
- try:
-
-
-
-
- from nt import _isdir as isdir
- except ImportError:
-
- pass
|