summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/ntpath.py19
-rw-r--r--Lib/posixpath.py8
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2024-04-07-18-42-09.gh-issue-117607.C978BD.rst1
3 files changed, 16 insertions, 12 deletions
diff --git a/Lib/ntpath.py b/Lib/ntpath.py
index e810b65..b833e0b 100644
--- a/Lib/ntpath.py
+++ b/Lib/ntpath.py
@@ -805,6 +805,9 @@ supports_unicode_filenames = True
def relpath(path, start=None):
"""Return a relative version of a path"""
path = os.fspath(path)
+ if not path:
+ raise ValueError("no path specified")
+
if isinstance(path, bytes):
sep = b'\\'
curdir = b'.'
@@ -816,22 +819,20 @@ def relpath(path, start=None):
if start is None:
start = curdir
+ else:
+ start = os.fspath(start)
- if not path:
- raise ValueError("no path specified")
-
- start = os.fspath(start)
try:
- start_abs = abspath(normpath(start))
- path_abs = abspath(normpath(path))
+ start_abs = abspath(start)
+ path_abs = abspath(path)
start_drive, _, start_rest = splitroot(start_abs)
path_drive, _, path_rest = splitroot(path_abs)
if normcase(start_drive) != normcase(path_drive):
raise ValueError("path is on mount %r, start on mount %r" % (
path_drive, start_drive))
- start_list = [x for x in start_rest.split(sep) if x]
- path_list = [x for x in path_rest.split(sep) if x]
+ start_list = start_rest.split(sep) if start_rest else []
+ path_list = path_rest.split(sep) if path_rest else []
# Work out how much of the filepath is shared by start and path.
i = 0
for e1, e2 in zip(start_list, path_list):
@@ -842,7 +843,7 @@ def relpath(path, start=None):
rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
if not rel_list:
return curdir
- return join(*rel_list)
+ return sep.join(rel_list)
except (TypeError, ValueError, AttributeError, BytesWarning, DeprecationWarning):
genericpath._check_arg_types('relpath', path, start)
raise
diff --git a/Lib/posixpath.py b/Lib/posixpath.py
index 56b7915..f189c33 100644
--- a/Lib/posixpath.py
+++ b/Lib/posixpath.py
@@ -532,15 +532,17 @@ def relpath(path, start=None):
start = os.fspath(start)
try:
- start_list = [x for x in abspath(start).split(sep) if x]
- path_list = [x for x in abspath(path).split(sep) if x]
+ start_tail = abspath(start).lstrip(sep)
+ path_tail = abspath(path).lstrip(sep)
+ start_list = start_tail.split(sep) if start_tail else []
+ path_list = path_tail.split(sep) if path_tail else []
# Work out how much of the filepath is shared by start and path.
i = len(commonprefix([start_list, path_list]))
rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
if not rel_list:
return curdir
- return join(*rel_list)
+ return sep.join(rel_list)
except (TypeError, AttributeError, BytesWarning, DeprecationWarning):
genericpath._check_arg_types('relpath', path, start)
raise
diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-07-18-42-09.gh-issue-117607.C978BD.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-07-18-42-09.gh-issue-117607.C978BD.rst
new file mode 100644
index 0000000..0c17dfd
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-07-18-42-09.gh-issue-117607.C978BD.rst
@@ -0,0 +1 @@
+Speedup :func:`os.path.relpath`.