curdir = '.'
pardir = '..'
extsep = '.'
sep = '\\'
pathsep = ';'
altsep = '/'
defpath = '.;C:\\bin'
devnull = 'nul'
import os
import sys
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","isreserved","expanduser","expandvars","normpath",
"abspath","curdir","pardir","sep","pathsep","defpath","altsep",
"extsep","devnull","realpath","supports_unicode_filenames","relpath",
"samefile", "sameopenfile", "samestat", "commonpath", "isjunction",
"isdevdrive", "ALLOW_MISSING"]
def _get_bothseps(path):
if isinstance(path, bytes):
return b'\\/'
else:
return '\\/'
try:
from _winapi import (
LCMapStringEx as _LCMapStringEx,
LOCALE_NAME_INVARIANT as _LOCALE_NAME_INVARIANT,
LCMAP_LOWERCASE as _LCMAP_LOWERCASE)
def normcase(s):
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):
s = os.fspath(s)
if isinstance(s, bytes):
return os.fsencode(os.fsdecode(s).replace('/', '\\').lower())
return s.replace('/', '\\').lower()
def isabs(s):
s = os.fspath(s)
if isinstance(s, bytes):
sep = b'\\'
altsep = b'/'
colon_sep = b':\\'
double_sep = b'\\\\'
else:
sep = '\\'
altsep = '/'
colon_sep = ':\\'
double_sep = '\\\\'
s = s[:3].replace(altsep, sep)
return s.startswith(colon_sep, 1) or s.startswith(double_sep)
def join(path, *paths):
path = os.fspath(path)
if isinstance(path, bytes):
sep = b'\\'
seps = b'\\/'
colon_seps = b':\\/'
else:
sep = '\\'
seps = '\\/'
colon_seps = ':\\/'
try:
result_drive, result_root, result_path = splitroot(path)
for p in paths:
p_drive, p_root, p_path = splitroot(p)
if p_root:
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():
result_drive = p_drive
result_root = p_root
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 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
def splitdrive(p):
drive, root, tail = splitroot(p)
return drive, root + tail
try:
from nt import _path_splitroot_ex as splitroot
except ImportError:
def splitroot(p):
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:
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:
return empty, p[:1], p[1:]
elif normp[1:2] == colon:
if normp[2:3] == sep:
return p[:2], p[2:3], p[3:]
else:
return p[:2], empty, p[2:]
else:
return empty, empty, p
def split(p):
p = os.fspath(p)
seps = _get_bothseps(p)
d, r, p = splitroot(p)
i = len(p)
while i and p[i-1] not in seps:
i -= 1
head, tail = p[:i], p[i:] return d + r + head.rstrip(seps), tail
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__
def basename(p):
return split(p)[1]
def dirname(p):
return split(p)[0]
try:
from nt import _getvolumepathname
except ImportError:
_getvolumepathname = None
def ismount(path):
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
_reserved_chars = frozenset(
{chr(i) for i in range(32)} |
{'"', '*', ':', '<', '>', '?', '|', '/', '\\'}
)
_reserved_names = frozenset(
{'CON', 'PRN', 'AUX', 'NUL', 'CONIN$', 'CONOUT$'} |
{f'COM{c}' for c in '123456789\xb9\xb2\xb3'} |
{f'LPT{c}' for c in '123456789\xb9\xb2\xb3'}
)
def isreserved(path):
path = os.fsdecode(splitroot(path)[2]).replace(altsep, sep)
return any(_isreservedname(name) for name in reversed(path.split(sep)))
def _isreservedname(name):
if name[-1:] in ('.', ' '):
return name not in ('.', '..')
if _reserved_chars.intersection(name):
return True
return name.partition('.')[0].rstrip(' ').upper() in _reserved_names
def expanduser(path):
path = os.fspath(path)
if isinstance(path, bytes):
seps = b'\\/'
tilde = b'~'
else:
seps = '\\/'
tilde = '~'
if not path.startswith(tilde):
return path
i, n = 1, len(path)
while i < n and path[i] not in seps:
i += 1
if 'USERPROFILE' in os.environ:
userhome = os.environ['USERPROFILE']
elif 'HOMEPATH' not in os.environ:
return path
else:
drive = os.environ.get('HOMEDRIVE', '')
userhome = join(drive, os.environ['HOMEPATH'])
if i != 1: 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:
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:]
_varpattern = r"'[^']*'?|%(%|[^%]*%?)|\$(\$|[-\w]+|\{[^}]*\}?)"
_varsub = None
_varsubb = None
def expandvars(path):
path = os.fspath(path)
global _varsub, _varsubb
if isinstance(path, bytes):
if b'$' not in path and b'%' not in path:
return path
if not _varsubb:
import re
_varsubb = re.compile(_varpattern.encode(), re.ASCII).sub
sub = _varsubb
percent = b'%'
brace = b'{'
rbrace = b'}'
dollar = b'$'
environ = getattr(os, 'environb', None)
else:
if '$' not in path and '%' not in path:
return path
if not _varsub:
import re
_varsub = re.compile(_varpattern, re.ASCII).sub
sub = _varsub
percent = '%'
brace = '{'
rbrace = '}'
dollar = '$'
environ = os.environ
def repl(m):
lastindex = m.lastindex
if lastindex is None:
return m[0]
name = m[lastindex]
if lastindex == 1:
if name == percent:
return name
if not name.endswith(percent):
return m[0]
name = name[:-1]
else:
if name == dollar:
return name
if name.startswith(brace):
if not name.endswith(rbrace):
return m[0]
name = name[1:-1]
try:
if environ is None:
return os.fsencode(os.environ[os.fsdecode(name)])
else:
return environ[name]
except KeyError:
return m[0]
return sub(repl, path)
try:
from nt import _path_normpath as normpath
except ImportError:
def normpath(path):
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 not prefix and not comps:
comps.append(curdir)
return prefix + sep.join(comps)
try:
from nt import _getfullpathname
except ImportError: def abspath(path):
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)
else: def abspath(path):
try:
return _getfullpathname(normpath(path))
except (OSError, ValueError):
pass
path = os.fspath(path)
if not isabs(path):
if isinstance(path, bytes):
sep = b'\\'
getcwd = os.getcwdb
else:
sep = '\\'
getcwd = os.getcwd
drive, root, path = splitroot(path)
if drive or root:
try:
path = join(_getfullpathname(drive + root), path)
except (OSError, ValueError):
path = drive + sep + path
else:
path = join(getcwd(), path)
return normpath(path)
try:
from nt import _findfirstfile, _getfinalpathname, readlink as _nt_readlink
except ImportError:
def realpath(path, *, strict=False):
return abspath(path)
else:
def _readlink_deep(path, ignored_error=OSError):
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)
if not isabs(path):
if not islink(old_path):
path = old_path
break
path = normpath(join(dirname(old_path), path))
except ignored_error as ex:
if ex.winerror in allowed_winerror:
break
raise
except ValueError:
break
return path
def _getfinalpathname_nonstrict(path, ignored_error=OSError):
allowed_winerror = 1, 2, 3, 5, 21, 32, 50, 53, 65, 67, 87, 123, 161, 1005, 1920, 1921
tail = path[:0]
while path:
try:
path = _getfinalpathname(path)
return join(path, tail) if tail else path
except ignored_error as ex:
if ex.winerror not in allowed_winerror:
raise
try:
new_path = _readlink_deep(path,
ignored_error=ignored_error)
if new_path != path:
return join(new_path, tail) if tail else new_path
except ignored_error:
pass
if ex.winerror in (1, 5, 32, 50, 87, 1920, 1921):
try:
name = _findfirstfile(path)
path, _ = split(path)
except ignored_error:
path, name = split(path)
else:
path, name = split(path)
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()
devnull = b'nul'
if normcase(path) == devnull:
return b'\\\\.\\NUL'
else:
prefix = '\\\\?\\'
unc_prefix = '\\\\?\\UNC\\'
new_unc_prefix = '\\\\'
cwd = os.getcwd()
devnull = 'nul'
if normcase(path) == devnull:
return '\\\\.\\NUL'
had_prefix = path.startswith(prefix)
if strict is ALLOW_MISSING:
ignored_error = FileNotFoundError
strict = True
elif strict:
ignored_error = ()
else:
ignored_error = OSError
if not had_prefix and not isabs(path):
path = join(cwd, path)
try:
path = _getfinalpathname(path)
initial_winerror = 0
except ValueError as ex:
if strict:
raise OSError(str(ex)) from None
path = normpath(path)
except ignored_error as ex:
initial_winerror = ex.winerror
path = _getfinalpathname_nonstrict(path,
ignored_error=ignored_error)
if not had_prefix and path.startswith(prefix):
if path.startswith(unc_prefix):
spath = new_unc_prefix + path[len(unc_prefix):]
else:
spath = path[len(prefix):]
try:
if _getfinalpathname(spath) == path:
path = spath
except ValueError as ex:
pass
except OSError as ex:
if ex.winerror == initial_winerror:
path = spath
return path
supports_unicode_filenames = True
def relpath(path, start=None):
path = os.fspath(path)
if not path:
raise ValueError("no path specified")
if isinstance(path, bytes):
sep = b'\\'
curdir = b'.'
pardir = b'..'
else:
sep = '\\'
curdir = '.'
pardir = '..'
if start is None:
start = curdir
else:
start = os.fspath(start)
try:
start_abs = abspath(start)
path_abs = abspath(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 = start_rest.split(sep) if start_rest else []
path_list = path_rest.split(sep) if path_rest else []
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 sep.join(rel_list)
except (TypeError, ValueError, AttributeError, BytesWarning, DeprecationWarning):
genericpath._check_arg_types('relpath', path, start)
raise
def commonpath(paths):
paths = tuple(map(os.fspath, paths))
if not paths:
raise ValueError('commonpath() arg is an empty iterable')
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({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))
if len({r for d, r, p in drivesplits}) != 1:
if drive:
raise ValueError("Can't mix absolute and relative paths")
else:
raise ValueError("Can't mix rooted and not-rooted paths")
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:
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_isjunction as isjunction
from nt import _path_exists as exists
from nt import _path_lexists as lexists
except ImportError:
pass
try:
from nt import _path_isdevdrive
def isdevdrive(path):
try:
return _path_isdevdrive(abspath(path))
except OSError:
return False
except ImportError:
pass