Skip to content

Commit a7711a2

Browse files
authored
gh-117607: Speedup os.path.relpath() (GH-117608)
1 parent 424438b commit a7711a2

File tree

3 files changed

+16
-12
lines changed

3 files changed

+16
-12
lines changed

Lib/ntpath.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,9 @@ def realpath(path, *, strict=False):
805805
def relpath(path, start=None):
806806
"""Return a relative version of a path"""
807807
path = os.fspath(path)
808+
if not path:
809+
raise ValueError("no path specified")
810+
808811
if isinstance(path, bytes):
809812
sep = b'\\'
810813
curdir = b'.'
@@ -816,22 +819,20 @@ def relpath(path, start=None):
816819

817820
if start is None:
818821
start = curdir
822+
else:
823+
start = os.fspath(start)
819824

820-
if not path:
821-
raise ValueError("no path specified")
822-
823-
start = os.fspath(start)
824825
try:
825-
start_abs = abspath(normpath(start))
826-
path_abs = abspath(normpath(path))
826+
start_abs = abspath(start)
827+
path_abs = abspath(path)
827828
start_drive, _, start_rest = splitroot(start_abs)
828829
path_drive, _, path_rest = splitroot(path_abs)
829830
if normcase(start_drive) != normcase(path_drive):
830831
raise ValueError("path is on mount %r, start on mount %r" % (
831832
path_drive, start_drive))
832833

833-
start_list = [x for x in start_rest.split(sep) if x]
834-
path_list = [x for x in path_rest.split(sep) if x]
834+
start_list = start_rest.split(sep) if start_rest else []
835+
path_list = path_rest.split(sep) if path_rest else []
835836
# Work out how much of the filepath is shared by start and path.
836837
i = 0
837838
for e1, e2 in zip(start_list, path_list):
@@ -842,7 +843,7 @@ def relpath(path, start=None):
842843
rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
843844
if not rel_list:
844845
return curdir
845-
return join(*rel_list)
846+
return sep.join(rel_list)
846847
except (TypeError, ValueError, AttributeError, BytesWarning, DeprecationWarning):
847848
genericpath._check_arg_types('relpath', path, start)
848849
raise

Lib/posixpath.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -532,15 +532,17 @@ def relpath(path, start=None):
532532
start = os.fspath(start)
533533

534534
try:
535-
start_list = [x for x in abspath(start).split(sep) if x]
536-
path_list = [x for x in abspath(path).split(sep) if x]
535+
start_tail = abspath(start).lstrip(sep)
536+
path_tail = abspath(path).lstrip(sep)
537+
start_list = start_tail.split(sep) if start_tail else []
538+
path_list = path_tail.split(sep) if path_tail else []
537539
# Work out how much of the filepath is shared by start and path.
538540
i = len(commonprefix([start_list, path_list]))
539541

540542
rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
541543
if not rel_list:
542544
return curdir
543-
return join(*rel_list)
545+
return sep.join(rel_list)
544546
except (TypeError, AttributeError, BytesWarning, DeprecationWarning):
545547
genericpath._check_arg_types('relpath', path, start)
546548
raise
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Speedup :func:`os.path.relpath`.

0 commit comments

Comments
 (0)