8000 Refactor `os.path` · python/cpython@f5bbaf6 · GitHub
[go: up one dir, main page]

Skip to content

Commit f5bbaf6

Browse files
committed
Refactor os.path
1 parent afc7bbc commit f5bbaf6

File tree

2 files changed

+85
-97
lines changed

2 files changed

+85
-97
lines changed

Lib/ntpath.py

Lines changed: 77 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,17 @@ def _get_bothseps(path):
4747
LCMapStringEx as _LCMapStringEx,
4848
LOCALE_NAME_INVARIANT as _LOCALE_NAME_INVARIANT,
4949
LCMAP_LOWERCASE as _LCMAP_LOWERCASE)
50+
except ImportError:
51+
def normcase(s):
52+
"""Normalize case of pathname.
5053
54+
Makes all characters lowercase and all slashes into backslashes.
55+
"""
56+
s = os.fspath(s)
57+
if isinstance(s, bytes):
58+
return os.fsencode(os.fsdecode(s).replace('/', '\\').lower())
59+
return s.replace('/', '\\').lower()
60+
else:
5161
def normcase(s):
5262
"""Normalize case of pathname.
5363
@@ -66,16 +76,6 @@ def normcase(s):
6676
return _LCMapStringEx(_LOCALE_NAME_INVARIANT,
6777
_LCMAP_LOWERCASE,
6878
s.replace('/', '\\'))
69-
except ImportError:
70-
def normcase(s):
71-
"""Normalize case of pathname.
72-
73-
Makes all characters lowercase and all slashes into backslashes.
74-
"""
75-
s = os.fspath(s)
76-
if isinstance(s, bytes):
77-
return os.fsencode(os.fsdecode(s).replace('/', '\\').lower())
78-
return s.replace('/', '\\').lower()
7979

8080

8181
def isabs(s):
@@ -279,9 +279,9 @@ def isjunction(path):
279279
"""Test whether a path is a junction"""
280280
try:
281281
st = os.lstat(path)
282+
return st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT
282283
except (OSError, ValueError, AttributeError):
283284
return False
284-
return bool(st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT)
285285
else:
286286
# Use genericpath.isjunction as imported above
287287
pass
@@ -301,6 +301,8 @@ def isjunction(path):
301301
from nt import _getvolumepathname
302302
except ImportError:
303303
_getvolumepathname = None
304+
305+
304306
def ismount(path):
305307
"""Test whether a path is a mount point (a drive root, the root of a
306308
share, or a mounted volume)"""
@@ -312,24 +314,22 @@ def ismount(path):
312314
return not tail
313315
if root and not tail:
314316
return True
315-
316-
if _getvolumepathname:
317-
x = path.rstrip(seps)
318-
y =_getvolumepathname(path).rstrip(seps)
319-
return x.casefold() == y.casefold()
320-
else:
317+
if not _getvolumepathname:
321318
return False
319+
x = path.rstrip(seps)
320+
y = _getvolumepathname(path).rstrip(seps)
321+
return x.casefold() == y.casefold()
322322

323323

324324
_reserved_chars = frozenset(
325-
{chr(i) for i in range(32)} |
326-
{'"', '*', ':', '<', '>', '?', '|', '/', '\\'}
325+
{chr(i) for i in range(32)}
326+
| {'"', '*', ':', '<', '>', '?', '|', '/', '\\'}
327327
)
328328

329329
_reserved_names = frozenset(
330-
{'CON', 'PRN', 'AUX', 'NUL', 'CONIN$', 'CONOUT$'} |
331-
{f'COM{c}' for c in '123456789\xb9\xb2\xb3'} |
332-
{f'LPT{c}' for c in '123456789\xb9\xb2\xb3'}
330+
{'CON', 'PRN', 'AUX', 'NUL', 'CONIN$', 'CONOUT$'}
331+
| {f'COM{c}' for c in '123456789\xb9\xb2\xb3'}
332+
| {f'LPT{c}' for c in '123456789\xb9\xb2\xb3'}
333333
)
334334

335335
def isreserved(path):
@@ -352,9 +352,7 @@ def _isreservedname(name):
352352
# DOS device names are reserved (e.g. "nul" or "nul .txt"). The rules
353353
# are complex and vary across Windows versions. On the side of
354354
# caution, return True for names that may not be reserved.
355-
if name.partition('.')[0].rstrip(' ').upper() in _reserved_names:
356-
return True
357-
return False
355+
return name.partition('.')[0].rstrip(' ').upper() in _reserved_names
358356

359357

360358
# Expand paths beginning with '~' or '~user'.
@@ -477,19 +475,17 @@ def expandvars(path):
477475
pathlen = len(path)
478476
try:
479477
index = path.index(percent)
478+
var = path[:index]
479+
if environ is None:
480+
value = os.fsencode(os.environ[os.fsdecode(var)])
481+
else:
482+
value = environ[var]
483+
res += value
480484
except ValueError:
481485
res += percent + path
482486
index = pathlen - 1
483-
else:
484-
var = path[:index]
485-
try:
486-
if environ is None:
487-
value = os.fsencode(os.environ[os.fsdecode(var)])
488-
else:
489-
value = environ[var]
490-
except KeyError:
491-
value = percent + var + percent
492-
res += value
487+
except KeyError:
488+
res += percent + var + percent
493489
elif c == dollar: # variable or '$$'
494490
if path[index + 1:index + 2] == dollar:
495491
res += c
@@ -499,19 +495,17 @@ def expandvars(path):
499495
pathlen = len(path)
500496
try:
501497
index = path.index(rbrace)
498+
var = path[:index]
499+
if environ is None:
500+
value = os.fsencode(os.environ[os.fsdecode(var)])
501+
else:
502+
value = environ[var]
503+
res += value
502504
except ValueError:
503505
res += dollar + brace + path
504506
index = pathlen - 1
505-
else:
506-
var = path[:index]
507-
try:
508-
if environ is None:
509-
value = os.fsencode(os.environ[os.fsdecode(var)])
510-
else:
511-
value = environ[var]
512-
except KeyError:
513-
value = dollar + brace + var + rbrace
514-
res += value
507+
except KeyError:
508+
res += dollar + brace + var + rbrace
515509
else:
516510
var = path[:0]
517511
index += 1
@@ -525,9 +519,9 @@ def expandvars(path):
525519
value = os.fsencode(os.environ[os.fsdecode(var)])
526520
else:
527521
value = environ[var]
522+
res += value
528523
except KeyError:
529-
value = dollar + var
530-
res += value
524+
res += dollar + var
531525
if c:
532526
index -= 1
533527
else:
@@ -542,6 +536,12 @@ def expandvars(path):
542536
try:
543537
from nt import _path_normpath
544538

539+
def normpath(path):
540+
"""Normalize path, eliminating double slashes, etc."""
541+
path = os.fspath(path)
542+
if isinstance(path, bytes):
543+
return os.fsencode(_path_normpath(os.fsdecode(path))) or b"."
544+
return _path_normpath(path) or "."
545545
except ImportError:
546546
def normpath(path):
547547
"""Normalize path, eliminating double slashes, etc."""
@@ -564,29 +564,20 @@ def normpath(path):
564564
while i < len(comps):
565565
if not comps[i] or comps[i] == curdir:
566566
del comps[i]
567-
elif comps[i] == pardir:
568-
if i > 0 and comps[i-1] != pardir:
569-
del comps[i-1:i+1]
570-
i -= 1
571-
elif i == 0 and root:
572-
del comps[i]
573-
else:
574-
i += 1
567+
elif comps[i] != pardir:
568+
i += 1
569+
elif i > 0 and comps[i-1] != pardir:
570+
del comps[i-1:i+1]
571+
i -= 1
572+
elif i == 0 and root:
573+
del comps[i]
575574
else:
576575
i += 1
577576
# If the path is now empty, substitute '.'
578577
if not prefix and not comps:
579578
comps.append(curdir)
580579
return prefix + sep.join(comps)
581580

582-
else:
583-
def normpath(path):
584-
"""Normalize path, eliminating double slashes, etc."""
585-
path = os.fspath(path)
586-
if isinstance(path, bytes):
587-
return os.fsencode(_path_normpath(os.fsdecode(path))) or b"."
588-
return _path_normpath(path) or "."
589-
590581

591582
def _abspath_fallback(path):
592583
"""Return the absolute version of a path as a fallback function in case
@@ -607,10 +598,8 @@ def _abspath_fallback(path):
607598
# Return an absolute path.
608599
try:
609600
from nt import _getfullpathname
610-
611601
except ImportError: # not running on Windows - mock up something sensible
612602
abspath = _abspath_fallback
613-
614603
else: # use native Windows method on Windows
615604
def abspath(path):
616605
"""Return the absolute version of a path."""
@@ -697,28 +686,28 @@ def _getfinalpathname_nonstrict(path):
697686
except OSError as ex:
698687
if ex.winerror not in allowed_winerror:
699688
raise
689+
try:
690+
# The OS could not resolve this path fully, so we attempt
691+
# to follow the link ourselves. If we succeed, join the tail
692+
# and return.
693+
new_path = _readlink_deep(path)
694+
if new_path != path:
695+
return join(new_path, tail) if tail else new_path
696+
except OSError:
697+
# If we fail to readlink(), let's keep traversing
698+
pass
699+
# If we get these errors, try to get the real name of the file without accessing it.
700+
if ex.winerror in (1, 5, 32, 50, 87, 1920, 1921):
700701
try:
701-
# The OS could not resolve this path fully, so we attempt
702-
# to follow the link ourselves. If we succeed, join the tail
703-
# and return.
704-
new_path = _readlink_deep(path)
705-
if new_path != path:
706-
return join(new_path, tail) if tail else new_path
702+
name = _findfirstfile(path)
703+
path, _ = split(path)
707704
except OSError:
708-
# If we fail to readlink(), let's keep traversing
709-
pass
710-
# If we get these errors, try to get the real name of the file without accessing it.
711-
if ex.winerror in (1, 5, 32, 50, 87, 1920, 1921):
712-
try:
713-
name = _findfirstfile(path)
714-
path, _ = split(path)
715-
except OSError:
716-
path, name = split(path)
717-
else:
718705
path, name = split(path)
719-
if path and not name:
720-
return path + tail
721-
tail = join(name, tail) if tail else name
706+
else:
707+
path, name = split(path)
708+
if path and not name:
709+
return path + tail
710+
tail = join(name, tail) if tail else name
722711
return tail
723712

724713
def realpath(path, *, strict=False):
@@ -904,12 +893,13 @@ def commonpath(paths):
904893

905894
try:
906895
from nt import _path_isdevdrive
896+
except ImportError:
897+
# Use genericpath.isdevdrive as imported above
898+
pass
899+
else:
907900
def isdevdrive(path):
908901
"""Determines whether the specified path is on a Windows Dev Drive."""
909902
try:
910903
return _path_isdevdrive(abspath(path))
911904
except OSError:
912905
return False
913-
except ImportError:
914-
# Use genericpath.isdevdrive as imported above
915-
pass

Lib/posixpath.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,9 @@ def split(p):
117117
def splitext(p):
118118
p = os.fspath(p)
119119
if isinstance(p, bytes):
120-
sep = b'/'
121-
extsep = b'.'
120+
return genericpath._splitext(p, b'/', None, b'.')
122121
else:
123-
sep = '/'
124-
extsep = '.'
125-
return genericpath._splitext(p, sep, None, extsep)
122+
return genericpath._splitext(p, '/', None, '.')
126123
splitext.__doc__ = genericpath._splitext.__doc__
127124

128125
# Split a pathname into a drive specification and the rest of the
@@ -248,9 +245,7 @@ def expanduser(path):
248245
# bpo-10496: if the user name from the path doesn't exist in the
249246
# password database, return the path unchanged
250247
return path
251-
elif 'HOME' in os.environ:
252-
userhome = os.environ['HOME']
253-
else:
248+
elif 'HOME' not in os.environ:
254249
try:
255250
import pwd
256251
userhome = pwd.getpwuid(os.getuid()).pw_dir
@@ -259,6 +254,8 @@ def expanduser(path):
259254
# bpo-10496: if the current user identifier doesn't exist in the
260255
# password database, return the path unchanged
261256
return path
257+
else:
258+
userhome = os.environ['HOME']
262259

263260
# if no user home, return the path unchanged on VxWorks
264261
if userhome is None and sys.platform == "vxworks":
@@ -361,14 +358,15 @@ def _normpath_fallback(path):
361358

362359
try:
363360
from posix import _path_normpath
361+
except ImportError:
362+
normpath = _normpath_fallback
363+
else:
364364
def normpath(path):
365365
"""Normalize path, eliminating double slashes, etc."""
366366
path = os.fspath(path)
367367
if isinstance(path, bytes):
368368
return os.fsencode(_path_normpath(os.fsdecode(path))) or b"."
369369
return _path_normpath(path) or "."
370-
except ImportError:
371-
normpath = _normpath_fallback
372370

373371

374372
def abspath(path):

0 commit comments

Comments
 (0)
0