diff --git a/Lib/ntpath.py b/Lib/ntpath.py index ecfc7d48dbb192..0650f14f89f10b 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -102,11 +102,11 @@ def join(path, *paths): if isinstance(path, bytes): sep = b'\\' seps = b'\\/' - colon = b':' + colon_seps = b':\\/' else: sep = '\\' seps = '\\/' - colon = ':' + colon_seps = ':\\/' try: if not paths: 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 ## 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): + 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): @@ -279,7 +279,7 @@ def isjunction(path): st = os.lstat(path) except (OSError, ValueError, AttributeError): 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: # Use genericpath.isjunction as imported above pass @@ -340,8 +340,8 @@ def isreserved(path): def _isreservedname(name): """Return true if the filename is reserved by the system.""" # Trailing dots and spaces are reserved. - if name.endswith(('.', ' ')) and name not in ('.', '..'): - return True + if name[-1:] in ('.', ' '): + return name not in ('.', '..') # Wildcards, separators, colon, and pipe (*?"<>/\:|) are reserved. # ASCII control characters (0-31) are reserved. # 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 # are complex and vary across Windows versions. On the side of # caution, return True for names that may not be reserved. - if name.partition('.')[0].rstrip(' ').upper() in _reserved_names: - return True - return False + return name.partition('.')[0].rstrip(' ').upper() in _reserved_names # Expand paths beginning with '~' or '~user'. @@ -381,13 +379,10 @@ def expanduser(path): if 'USERPROFILE' in os.environ: userhome = os.environ['USERPROFILE'] - elif not 'HOMEPATH' in os.environ: + elif 'HOMEPATH' not in os.environ: return path else: - try: - drive = os.environ['HOMEDRIVE'] - except KeyError: - drive = '' + drive = os.environ.get('HOMEDRIVE', '') userhome = join(drive, os.environ['HOMEPATH']) if i != 1: #~user @@ -727,7 +722,8 @@ def realpath(path, *, strict=False): new_unc_prefix = b'\\\\' cwd = os.getcwdb() # 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' else: prefix = '\\\\?\\' @@ -735,7 +731,8 @@ def realpath(path, *, strict=False): new_unc_prefix = '\\\\' cwd = os.getcwd() # bpo-38081: Special case for realpath('nul') - if normcase(path) == normcase(devnull): + devnull = 'nul' + if normcase(path) == devnull: return '\\\\.\\NUL' had_prefix = path.startswith(prefix) if not had_prefix and not isabs(path): diff --git a/Lib/posixpath.py b/Lib/posixpath.py index 4fc02be69bd6e1..76ee721bfb5e33 100644 --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -213,15 +213,8 @@ def ismount(path): except (OSError, ValueError): return False - dev1 = s1.st_dev - dev2 = s2.st_dev - 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 + # path/.. on a different device as path or the same i-node as path + return s1.st_dev != s2.st_dev or s1.st_ino == s2.st_ino # Expand paths beginning with '~' or '~user'. @@ -270,7 +263,7 @@ def expanduser(path): return path name = path[1:i] if isinstance(name, bytes): - name = str(name, 'ASCII') + name = name.decode('ascii') try: pwent = pwd.getpwnam(name) except KeyError: @@ -359,21 +352,19 @@ def normpath(path): path = os.fspath(path) if isinstance(path, bytes): sep = b'/' - empty = b'' dot = b'.' dotdot = b'..' else: sep = '/' - empty = '' dot = '.' dotdot = '..' - if path == empty: + if not path: return dot _, initial_slashes, path = splitroot(path) comps = path.split(sep) new_comps = [] for comp in comps: - if comp in (empty, dot): + if not comp or comp == dot: continue if (comp != dotdot or (not initial_slashes and not new_comps) or (new_comps and new_comps[-1] == dotdot)): @@ -396,12 +387,12 @@ def normpath(path): def abspath(path): """Return an absolute path.""" path = os.fspath(path) - if not isabs(path): - if isinstance(path, bytes): - cwd = os.getcwdb() - else: - cwd = os.getcwd() - path = join(cwd, path) + if isinstance(path, bytes): + if not path.startswith(b'/'): + path = join(os.getcwdb(), path) + else: + if not path.startswith('/'): + path = join(os.getcwd(), path) return normpath(path) @@ -417,6 +408,7 @@ def realpath(filename, *, strict=False): # Join two paths, normalizing and eliminating any symbolic links # encountered in the second path. +# Two leading slashes are replaced by a single slash. def _joinrealpath(path, rest, strict, seen): if isinstance(path, bytes): sep = b'/' @@ -427,7 +419,7 @@ def _joinrealpath(path, rest, strict, seen): curdir = '.' pardir = '..' - if isabs(rest): + if rest.startswith(sep): rest = rest[1:] path = sep @@ -439,10 +431,15 @@ def _joinrealpath(path, rest, strict, seen): if name == pardir: # parent dir if path: - path, name = split(path) + parent, name = split(path) if name == pardir: - path = join(path, pardir, pardir) + # ../.. + path = join(path, pardir) + else: + # foo/bar/.. -> foo + path = parent else: + # .. path = pardir continue newpath = join(path, name) diff --git a/Misc/ACKS b/Misc/ACKS index 03e458d170d2b8..fe014a364dd82d 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -191,6 +191,7 @@ Finn Bock Paul Boddie Matthew Boedicker Robin Boerdijk +Wannes Boeykens Andra Bogildea Matt Bogosian Nikolay Bogoychev diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-03-29-15-04-13.gh-issue-117349.OB9kQQ.rst b/Misc/NEWS.d/next/Core and Builtins/2024-03-29-15-04-13.gh-issue-117349.OB9kQQ.rst new file mode 100644 index 00000000000000..7a7bc689002017 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-03-29-15-04-13.gh-issue-117349.OB9kQQ.rst @@ -0,0 +1 @@ +Optimise several functions in :mod:`os.path`.