mirror of
https://github.com/python/cpython.git
synced 2025-08-30 13:38:43 +00:00
gh-117349: Micro-optimize a few os.path
functions (#117350)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com> Co-authored-by: Barney Gale <barney.gale@gmail.com> Co-authored-by: Pieter Eendebak <pieter.eendebak@gmail.com>
This commit is contained in:
parent
8eda146e87
commit
cae4cdd07d
4 changed files with 35 additions and 39 deletions
|
@ -102,11 +102,11 @@ def join(path, *paths):
|
||||||
if isinstance(path, bytes):
|
if isinstance(path, bytes):
|
||||||
sep = b'\\'
|
sep = b'\\'
|
||||||
seps = b'\\/'
|
seps = b'\\/'
|
||||||
colon = b':'
|
colon_seps = b':\\/'
|
||||||
else:
|
else:
|
||||||
sep = '\\'
|
sep = '\\'
|
||||||
seps = '\\/'
|
seps = '\\/'
|
||||||
colon = ':'
|
colon_seps = ':\\/'
|
||||||
try:
|
try:
|
||||||
if not paths:
|
if not paths:
|
||||||
path[:0] + sep #23780: Ensure compatible data type even if p is null.
|
path[:0] + sep #23780: Ensure compatible data type even if p is null.
|
||||||
|
@ -135,7 +135,7 @@ def join(path, *paths):
|
||||||
result_path = result_path + p_path
|
result_path = result_path + p_path
|
||||||
## add separator between UNC and non-absolute path
|
## add separator between UNC and non-absolute path
|
||||||
if (result_path and not result_root and
|
if (result_path and not result_root and
|
||||||
result_drive and result_drive[-1:] not in colon + seps):
|
result_drive and result_drive[-1] not in colon_seps):
|
||||||
return result_drive + sep + result_path
|
return result_drive + sep + result_path
|
||||||
return result_drive + result_root + result_path
|
return result_drive + result_root + result_path
|
||||||
except (TypeError, AttributeError, BytesWarning):
|
except (TypeError, AttributeError, BytesWarning):
|
||||||
|
@ -279,7 +279,7 @@ if hasattr(os.stat_result, 'st_reparse_tag'):
|
||||||
st = os.lstat(path)
|
st = os.lstat(path)
|
||||||
except (OSError, ValueError, AttributeError):
|
except (OSError, ValueError, AttributeError):
|
||||||
return False
|
return False
|
||||||
return bool(st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT)
|
return st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT
|
||||||
else:
|
else:
|
||||||
# Use genericpath.isjunction as imported above
|
# Use genericpath.isjunction as imported above
|
||||||
pass
|
pass
|
||||||
|
@ -340,8 +340,8 @@ def isreserved(path):
|
||||||
def _isreservedname(name):
|
def _isreservedname(name):
|
||||||
"""Return true if the filename is reserved by the system."""
|
"""Return true if the filename is reserved by the system."""
|
||||||
# Trailing dots and spaces are reserved.
|
# Trailing dots and spaces are reserved.
|
||||||
if name.endswith(('.', ' ')) and name not in ('.', '..'):
|
if name[-1:] in ('.', ' '):
|
||||||
return True
|
return name not in ('.', '..')
|
||||||
# Wildcards, separators, colon, and pipe (*?"<>/\:|) are reserved.
|
# Wildcards, separators, colon, and pipe (*?"<>/\:|) are reserved.
|
||||||
# ASCII control characters (0-31) are reserved.
|
# ASCII control characters (0-31) are reserved.
|
||||||
# Colon is reserved for file streams (e.g. "name:stream[:type]").
|
# Colon is reserved for file streams (e.g. "name:stream[:type]").
|
||||||
|
@ -350,9 +350,7 @@ def _isreservedname(name):
|
||||||
# DOS device names are reserved (e.g. "nul" or "nul .txt"). The rules
|
# DOS device names are reserved (e.g. "nul" or "nul .txt"). The rules
|
||||||
# are complex and vary across Windows versions. On the side of
|
# are complex and vary across Windows versions. On the side of
|
||||||
# caution, return True for names that may not be reserved.
|
# caution, return True for names that may not be reserved.
|
||||||
if name.partition('.')[0].rstrip(' ').upper() in _reserved_names:
|
return name.partition('.')[0].rstrip(' ').upper() in _reserved_names
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
# Expand paths beginning with '~' or '~user'.
|
# Expand paths beginning with '~' or '~user'.
|
||||||
|
@ -381,13 +379,10 @@ def expanduser(path):
|
||||||
|
|
||||||
if 'USERPROFILE' in os.environ:
|
if 'USERPROFILE' in os.environ:
|
||||||
userhome = os.environ['USERPROFILE']
|
userhome = os.environ['USERPROFILE']
|
||||||
elif not 'HOMEPATH' in os.environ:
|
elif 'HOMEPATH' not in os.environ:
|
||||||
return path
|
return path
|
||||||
else:
|
else:
|
||||||
try:
|
drive = os.environ.get('HOMEDRIVE', '')
|
||||||
drive = os.environ['HOMEDRIVE']
|
|
||||||
except KeyError:
|
|
||||||
drive = ''
|
|
||||||
userhome = join(drive, os.environ['HOMEPATH'])
|
userhome = join(drive, os.environ['HOMEPATH'])
|
||||||
|
|
||||||
if i != 1: #~user
|
if i != 1: #~user
|
||||||
|
@ -727,7 +722,8 @@ else:
|
||||||
new_unc_prefix = b'\\\\'
|
new_unc_prefix = b'\\\\'
|
||||||
cwd = os.getcwdb()
|
cwd = os.getcwdb()
|
||||||
# bpo-38081: Special case for realpath(b'nul')
|
# bpo-38081: Special case for realpath(b'nul')
|
||||||
if normcase(path) == normcase(os.fsencode(devnull)):
|
devnull = b'nul'
|
||||||
|
if normcase(path) == devnull:
|
||||||
return b'\\\\.\\NUL'
|
return b'\\\\.\\NUL'
|
||||||
else:
|
else:
|
||||||
prefix = '\\\\?\\'
|
prefix = '\\\\?\\'
|
||||||
|
@ -735,7 +731,8 @@ else:
|
||||||
new_unc_prefix = '\\\\'
|
new_unc_prefix = '\\\\'
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
# bpo-38081: Special case for realpath('nul')
|
# bpo-38081: Special case for realpath('nul')
|
||||||
if normcase(path) == normcase(devnull):
|
devnull = 'nul'
|
||||||
|
if normcase(path) == devnull:
|
||||||
return '\\\\.\\NUL'
|
return '\\\\.\\NUL'
|
||||||
had_prefix = path.startswith(prefix)
|
had_prefix = path.startswith(prefix)
|
||||||
if not had_prefix and not isabs(path):
|
if not had_prefix and not isabs(path):
|
||||||
|
|
|
@ -213,15 +213,8 @@ def ismount(path):
|
||||||
except (OSError, ValueError):
|
except (OSError, ValueError):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
dev1 = s1.st_dev
|
# path/.. on a different device as path or the same i-node as path
|
||||||
dev2 = s2.st_dev
|
return s1.st_dev != s2.st_dev or s1.st_ino == s2.st_ino
|
||||||
if dev1 != dev2:
|
|
||||||
return True # path/.. on a different device as path
|
|
||||||
ino1 = s1.st_ino
|
|
||||||
ino2 = s2.st_ino
|
|
||||||
if ino1 == ino2:
|
|
||||||
return True # path/.. is the same i-node as path
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
# Expand paths beginning with '~' or '~user'.
|
# Expand paths beginning with '~' or '~user'.
|
||||||
|
@ -270,7 +263,7 @@ def expanduser(path):
|
||||||
return path
|
return path
|
||||||
name = path[1:i]
|
name = path[1:i]
|
||||||
if isinstance(name, bytes):
|
if isinstance(name, bytes):
|
||||||
name = str(name, 'ASCII')
|
name = name.decode('ascii')
|
||||||
try:
|
try:
|
||||||
pwent = pwd.getpwnam(name)
|
pwent = pwd.getpwnam(name)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
@ -359,21 +352,19 @@ except ImportError:
|
||||||
path = os.fspath(path)
|
path = os.fspath(path)
|
||||||
if isinstance(path, bytes):
|
if isinstance(path, bytes):
|
||||||
sep = b'/'
|
sep = b'/'
|
||||||
empty = b''
|
|
||||||
dot = b'.'
|
dot = b'.'
|
||||||
dotdot = b'..'
|
dotdot = b'..'
|
||||||
else:
|
else:
|
||||||
sep = '/'
|
sep = '/'
|
||||||
empty = ''
|
|
||||||
dot = '.'
|
dot = '.'
|
||||||
dotdot = '..'
|
dotdot = '..'
|
||||||
if path == empty:
|
if not path:
|
||||||
return dot
|
return dot
|
||||||
_, initial_slashes, path = splitroot(path)
|
_, initial_slashes, path = splitroot(path)
|
||||||
comps = path.split(sep)
|
comps = path.split(sep)
|
||||||
new_comps = []
|
new_comps = []
|
||||||
for comp in comps:
|
for comp in comps:
|
||||||
if comp in (empty, dot):
|
if not comp or comp == dot:
|
||||||
continue
|
continue
|
||||||
if (comp != dotdot or (not initial_slashes and not new_comps) or
|
if (comp != dotdot or (not initial_slashes and not new_comps) or
|
||||||
(new_comps and new_comps[-1] == dotdot)):
|
(new_comps and new_comps[-1] == dotdot)):
|
||||||
|
@ -396,12 +387,12 @@ else:
|
||||||
def abspath(path):
|
def abspath(path):
|
||||||
"""Return an absolute path."""
|
"""Return an absolute path."""
|
||||||
path = os.fspath(path)
|
path = os.fspath(path)
|
||||||
if not isabs(path):
|
if isinstance(path, bytes):
|
||||||
if isinstance(path, bytes):
|
if not path.startswith(b'/'):
|
||||||
cwd = os.getcwdb()
|
path = join(os.getcwdb(), path)
|
||||||
else:
|
else:
|
||||||
cwd = os.getcwd()
|
if not path.startswith('/'):
|
||||||
path = join(cwd, path)
|
path = join(os.getcwd(), path)
|
||||||
return normpath(path)
|
return normpath(path)
|
||||||
|
|
||||||
|
|
||||||
|
@ -417,6 +408,7 @@ symbolic links encountered in the path."""
|
||||||
|
|
||||||
# Join two paths, normalizing and eliminating any symbolic links
|
# Join two paths, normalizing and eliminating any symbolic links
|
||||||
# encountered in the second path.
|
# encountered in the second path.
|
||||||
|
# Two leading slashes are replaced by a single slash.
|
||||||
def _joinrealpath(path, rest, strict, seen):
|
def _joinrealpath(path, rest, strict, seen):
|
||||||
if isinstance(path, bytes):
|
if isinstance(path, bytes):
|
||||||
sep = b'/'
|
sep = b'/'
|
||||||
|
@ -427,7 +419,7 @@ def _joinrealpath(path, rest, strict, seen):
|
||||||
curdir = '.'
|
curdir = '.'
|
||||||
pardir = '..'
|
pardir = '..'
|
||||||
|
|
||||||
if isabs(rest):
|
if rest.startswith(sep):
|
||||||
rest = rest[1:]
|
rest = rest[1:]
|
||||||
path = sep
|
path = sep
|
||||||
|
|
||||||
|
@ -439,10 +431,15 @@ def _joinrealpath(path, rest, strict, seen):
|
||||||
if name == pardir:
|
if name == pardir:
|
||||||
# parent dir
|
# parent dir
|
||||||
if path:
|
if path:
|
||||||
path, name = split(path)
|
parent, name = split(path)
|
||||||
if name == pardir:
|
if name == pardir:
|
||||||
path = join(path, pardir, pardir)
|
# ../..
|
||||||
|
path = join(path, pardir)
|
||||||
|
else:
|
||||||
|
# foo/bar/.. -> foo
|
||||||
|
path = parent
|
||||||
else:
|
else:
|
||||||
|
# ..
|
||||||
path = pardir
|
path = pardir
|
||||||
continue
|
continue
|
||||||
newpath = join(path, name)
|
newpath = join(path, name)
|
||||||
|
|
|
@ -191,6 +191,7 @@ Finn Bock
|
||||||
Paul Boddie
|
Paul Boddie
|
||||||
Matthew Boedicker
|
Matthew Boedicker
|
||||||
Robin Boerdijk
|
Robin Boerdijk
|
||||||
|
Wannes Boeykens
|
||||||
Andra Bogildea
|
Andra Bogildea
|
||||||
Matt Bogosian
|
Matt Bogosian
|
||||||
Nikolay Bogoychev
|
Nikolay Bogoychev
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Optimise several functions in :mod:`os.path`.
|
Loading…
Add table
Add a link
Reference in a new issue