Update ntpath from CPython 3.10.6
@@ -23,6 +23,7 @@ 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",
@@ -41,14 +42,39 @@ def _get_bothseps(path):
# 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."""
+ Makes all characters lowercase and all slashes into backslashes.
+ """
s = os.fspath(s)
+ if not s:
+ return s
if isinstance(s, bytes):
- return s.replace(b'/', b'\\').lower()
+ 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()
@@ -312,12 +338,25 @@ def expanduser(path):
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)
- if i != 1: #~user
- userhome = join(dirname(userhome), path[1:i])
-
return userhome + path[i:]
@@ -622,7 +661,7 @@ else:
tail = join(name, tail) if tail else name
return tail
- def realpath(path):
+ def realpath(path, *, strict=False):
path = normpath(path)
if isinstance(path, bytes):
prefix = b'\\\\?\\'
@@ -647,6 +686,8 @@ else:
path = _getfinalpathname(path)
initial_winerror = 0
except OSError as ex:
+ if strict:
+ raise
initial_winerror = ex.winerror
path = _getfinalpathname_nonstrict(path)
# The path returned by _getfinalpathname will always start with \\?\ -
