Skip to content

Commit cae4cdd

Browse files
nineteendoAlexWaygoodbarneygaleeendebakpt
authored
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>
1 parent 8eda146 commit cae4cdd

File tree

4 files changed

+35
-39
lines changed

4 files changed

+35
-39
lines changed

Lib/ntpath.py

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,11 @@ def join(path, *paths):
102102
if isinstance(path, bytes):
103103
sep = b'\\'
104104
seps = b'\\/'
105-
colon = b':'
105+
colon_seps = b':\\/'
106106
else:
107107
sep = '\\'
108108
seps = '\\/'
109-
colon = ':'
109+
colon_seps = ':\\/'
110110
try:
111111
if not paths:
112112
path[:0] + sep #23780: Ensure compatible data type even if p is null.
@@ -135,7 +135,7 @@ def join(path, *paths):
135135
result_path = result_path + p_path
136136
## add separator between UNC and non-absolute path
137137
if (result_path and not result_root and
138-
result_drive and result_drive[-1:] not in colon + seps):
138+
result_drive and result_drive[-1] not in colon_seps):
139139
return result_drive + sep + result_path
140140
return result_drive + result_root + result_path
141141
except (TypeError, AttributeError, BytesWarning):
@@ -279,7 +279,7 @@ def isjunction(path):
279279
st = os.lstat(path)
280280
except (OSError, ValueError, AttributeError):
281281
return False
282-
return bool(st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT)
282+
return st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT
283283
else:
284284
# Use genericpath.isjunction as imported above
285285
pass
@@ -340,8 +340,8 @@ def isreserved(path):
340340
def _isreservedname(name):
341341
"""Return true if the filename is reserved by the system."""
342342
# Trailing dots and spaces are reserved.
343-
if name.endswith(('.', ' ')) and name not in ('.', '..'):
344-
return True
343+
if name[-1:] in ('.', ' '):
344+
return name not in ('.', '..')
345345
# Wildcards, separators, colon, and pipe (*?"<>/\:|) are reserved.
346346
# ASCII control characters (0-31) are reserved.
347347
# Colon is reserved for file streams (e.g. "name:stream[:type]").
@@ -350,9 +350,7 @@ def _isreservedname(name):
350350
# DOS device names are reserved (e.g. "nul" or "nul .txt"). The rules
351351
# are complex and vary across Windows versions. On the side of
352352
# caution, return True for names that may not be reserved.
353-
if name.partition('.')[0].rstrip(' ').upper() in _reserved_names:
354-
return True
355-
return False
353+
return name.partition('.')[0].rstrip(' ').upper() in _reserved_names
356354

357355

358356
# Expand paths beginning with '~' or '~user'.
@@ -381,13 +379,10 @@ def expanduser(path):
381379

382380
if 'USERPROFILE' in os.environ:
383381
userhome = os.environ['USERPROFILE']
384-
elif not 'HOMEPATH' in os.environ:
382+
elif 'HOMEPATH' not in os.environ:
385383
return path
386384
else:
387-
try:
388-
drive = os.environ['HOMEDRIVE']
389-
except KeyError:
390-
drive = ''
385+
drive = os.environ.get('HOMEDRIVE', '')
391386
userhome = join(drive, os.environ['HOMEPATH'])
392387

393388
if i != 1: #~user
@@ -727,15 +722,17 @@ def realpath(path, *, strict=False):
727722
new_unc_prefix = b'\\\\'
728723
cwd = os.getcwdb()
729724
# bpo-38081: Special case for realpath(b'nul')
730-
if normcase(path) == normcase(os.fsencode(devnull)):
725+
devnull = b'nul'
726+
if normcase(path) == devnull:
731727
return b'\\\\.\\NUL'
732728
else:
733729
prefix = '\\\\?\\'
734730
unc_prefix = '\\\\?\\UNC\\'
735731
new_unc_prefix = '\\\\'
736732
cwd = os.getcwd()
737733
# bpo-38081: Special case for realpath('nul')
738-
if normcase(path) == normcase(devnull):
734+
devnull = 'nul'
735+
if normcase(path) == devnull:
739736
return '\\\\.\\NUL'
740737
had_prefix = path.startswith(prefix)
741738
if not had_prefix and not isabs(path):

Lib/posixpath.py

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -213,15 +213,8 @@ def ismount(path):
213213
except (OSError, ValueError):
214214
return False
215215

216-
dev1 = s1.st_dev
217-
dev2 = s2.st_dev
218-
if dev1 != dev2:
219-
return True # path/.. on a different device as path
220-
ino1 = s1.st_ino
221-
ino2 = s2.st_ino
222-
if ino1 == ino2:
223-
return True # path/.. is the same i-node as path
224-
return False
216+
# path/.. on a different device as path or the same i-node as path
217+
return s1.st_dev != s2.st_dev or s1.st_ino == s2.st_ino
225218

226219

227220
# Expand paths beginning with '~' or '~user'.
@@ -270,7 +263,7 @@ def expanduser(path):
270263
return path
271264
name = path[1:i]
272265
if isinstance(name, bytes):
273-
name = str(name, 'ASCII')
266+
name = name.decode('ascii')
274267
try:
275268
pwent = pwd.getpwnam(name)
276269
except KeyError:
@@ -359,21 +352,19 @@ def normpath(path):
359352
path = os.fspath(path)
360353
if isinstance(path, bytes):
361354
sep = b'/'
362-
empty = b''
363355
dot = b'.'
364356
dotdot = b'..'
365357
else:
366358
sep = '/'
367-
empty = ''
368359
dot = '.'
369360
dotdot = '..'
370-
if path == empty:
361+
if not path:
371362
return dot
372363
_, initial_slashes, path = splitroot(path)
373364
comps = path.split(sep)
374365
new_comps = []
375366
for comp in comps:
376-
if comp in (empty, dot):
367+
if not comp or comp == dot:
377368
continue
378369
if (comp != dotdot or (not initial_slashes and not new_comps) or
379370
(new_comps and new_comps[-1] == dotdot)):
@@ -396,12 +387,12 @@ def normpath(path):
396387
def abspath(path):
397388
"""Return an absolute path."""
398389
path = os.fspath(path)
399-
if not isabs(path):
400-
if isinstance(path, bytes):
401-
cwd = os.getcwdb()
402-
else:
403-
cwd = os.getcwd()
404-
path = join(cwd, path)
390+
if isinstance(path, bytes):
391+
if not path.startswith(b'/'):
392+
path = join(os.getcwdb(), path)
393+
else:
394+
if not path.startswith('/'):
395+
path = join(os.getcwd(), path)
405396
return normpath(path)
406397

407398

@@ -417,6 +408,7 @@ def realpath(filename, *, strict=False):
417408

418409
# Join two paths, normalizing and eliminating any symbolic links
419410
# encountered in the second path.
411+
# Two leading slashes are replaced by a single slash.
420412
def _joinrealpath(path, rest, strict, seen):
421413
if isinstance(path, bytes):
422414
sep = b'/'
@@ -427,7 +419,7 @@ def _joinrealpath(path, rest, strict, seen):
427419
curdir = '.'
428420
pardir = '..'
429421

430-
if isabs(rest):
422+
if rest.startswith(sep):
431423
rest = rest[1:]
432424
path = sep
433425

@@ -439,10 +431,15 @@ def _joinrealpath(path, rest, strict, seen):
439431
if name == pardir:
440432
# parent dir
441433
if path:
442-
path, name = split(path)
434+
parent, name = split(path)
443435
if name == pardir:
444-
path = join(path, pardir, pardir)
436+
# ../..
437+
path = join(path, pardir)
438+
else:
439+
# foo/bar/.. -> foo
440+
path = parent
445441
else:
442+
# ..
446443
path = pardir
447444
continue
448445
newpath = join(path, name)

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ Finn Bock
191191
Paul Boddie
192192
Matthew Boedicker
193193
Robin Boerdijk
194+
Wannes Boeykens
194195
Andra Bogildea
195196
Matt Bogosian
196197
Nikolay Bogoychev
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Optimise several functions in :mod:`os.path`.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy