[Python-checkins] r54419 - in python/trunk: Doc/lib/libposixpath.tex Lib/ntpath.py Lib/posixpath.py Lib/test/test_ntpath.py Lib/test/test_posixpath.py Misc/ACKS Misc/NEWS

collin.winter python-checkins at python.org
Fri Mar 16 23:16:09 CET 2007


Author: collin.winter
Date: Fri Mar 16 23:16:08 2007
New Revision: 54419

Modified:
   python/trunk/Doc/lib/libposixpath.tex
   python/trunk/Lib/ntpath.py
   python/trunk/Lib/posixpath.py
   python/trunk/Lib/test/test_ntpath.py
   python/trunk/Lib/test/test_posixpath.py
   python/trunk/Misc/ACKS
   python/trunk/Misc/NEWS
Log:
Patch 1339796: add a relpath() function to os.path.

Modified: python/trunk/Doc/lib/libposixpath.tex
==============================================================================
--- python/trunk/Doc/lib/libposixpath.tex	(original)
+++ python/trunk/Doc/lib/libposixpath.tex	Fri Mar 16 23:16:08 2007
@@ -189,6 +189,15 @@
 \versionadded{2.2}
 \end{funcdesc}
 
+\begin{funcdesc}{relpath}{path\optional{, start}}
+Return a relative filepath to \var{path} either from the current
+directory or from an optional \var{start} point.
+
+\var{start} defaults to \member{os.curdir}.
+Availability:  Windows, \UNIX.
+\versionadded{2.6}
+\end{funcdesc}
+
 \begin{funcdesc}{samefile}{path1, path2}
 Return \code{True} if both pathname arguments refer to the same file or
 directory (as indicated by device number and i-node number).

Modified: python/trunk/Lib/ntpath.py
==============================================================================
--- python/trunk/Lib/ntpath.py	(original)
+++ python/trunk/Lib/ntpath.py	Fri Mar 16 23:16:08 2007
@@ -16,7 +16,7 @@
            "getatime","getctime", "islink","exists","lexists","isdir","isfile",
            "ismount","walk","expanduser","expandvars","normpath","abspath",
            "splitunc","curdir","pardir","sep","pathsep","defpath","altsep",
-           "extsep","devnull","realpath","supports_unicode_filenames"]
+           "extsep","devnull","realpath","supports_unicode_filenames","relpath"]
 
 # strings representing various path-related bits and pieces
 curdir = '.'
@@ -465,3 +465,29 @@
 # Win9x family and earlier have no Unicode filename support.
 supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and
                               sys.getwindowsversion()[3] >= 2)
+
+def relpath(path, start=curdir):
+    """Return a relative version of a path"""
+
+    if not path:
+        raise ValueError("no path specified")
+    start_list = abspath(start).split(sep)
+    path_list = abspath(path).split(sep)
+    if start_list[0].lower() != path_list[0].lower():
+        unc_path, rest = splitunc(path)
+        unc_start, rest = splitunc(start)
+        if bool(unc_path) ^ bool(unc_start):
+            raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
+                                                                % (path, start))
+        else:
+            raise ValueError("path is on drive %s, start on drive %s"
+                                                % (path_list[0], start_list[0]))
+    # Work out how much of the filepath is shared by start and path.
+    for i in range(min(len(start_list), len(path_list))):
+        if start_list[i].lower() != path_list[i].lower():
+            break
+    else:
+        i += 1
+
+    rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
+    return join(*rel_list)

Modified: python/trunk/Lib/posixpath.py
==============================================================================
--- python/trunk/Lib/posixpath.py	(original)
+++ python/trunk/Lib/posixpath.py	Fri Mar 16 23:16:08 2007
@@ -21,7 +21,7 @@
            "ismount","walk","expanduser","expandvars","normpath","abspath",
            "samefile","sameopenfile","samestat",
            "curdir","pardir","sep","pathsep","defpath","altsep","extsep",
-           "devnull","realpath","supports_unicode_filenames"]
+           "devnull","realpath","supports_unicode_filenames","relpath"]
 
 # strings representing various path-related bits and pieces
 curdir = '.'
@@ -382,3 +382,18 @@
     return path
 
 supports_unicode_filenames = False
+
+def relpath(path, start=curdir):
+    """Return a relative version of a path"""
+
+    if not path:
+        raise ValueError("no path specified")
+    
+    start_list = abspath(start).split(sep)
+    path_list = abspath(path).split(sep)
+    
+    # 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:]
+    return join(*rel_list)

Modified: python/trunk/Lib/test/test_ntpath.py
==============================================================================
--- python/trunk/Lib/test/test_ntpath.py	(original)
+++ python/trunk/Lib/test/test_ntpath.py	Fri Mar 16 23:16:08 2007
@@ -157,6 +157,16 @@
 else:
     tester('ntpath.abspath("C:\\")', "C:\\")
 
+currentdir = os.path.split(os.getcwd())[-1]
+tester('ntpath.relpath("a")', 'a')
+tester('ntpath.relpath(os.path.abspath("a"))', 'a')
+tester('ntpath.relpath("a/b")', 'a\\b')
+tester('ntpath.relpath("../a/b")', '..\\a\\b')
+tester('ntpath.relpath("a", "../b")', '..\\'+currentdir+'\\a')
+tester('ntpath.relpath("a/b", "../c")', '..\\'+currentdir+'\\a\\b')
+tester('ntpath.relpath("a", "b/c")', '..\\..\\a')
+tester('ntpath.relpath("//conky/mountpoint/a", "//conky/mountpoint/b/c")', '..\\..\\a')
+
 if errors:
     raise TestFailed(str(errors) + " errors.")
 elif verbose:

Modified: python/trunk/Lib/test/test_posixpath.py
==============================================================================
--- python/trunk/Lib/test/test_posixpath.py	(original)
+++ python/trunk/Lib/test/test_posixpath.py	Fri Mar 16 23:16:08 2007
@@ -2,7 +2,7 @@
 from test import test_support
 
 import posixpath, os
-from posixpath import realpath, abspath, join, dirname, basename
+from posixpath import realpath, abspath, join, dirname, basename, relpath
 
 # An absolute path to a temporary filename for testing. We can't rely on TESTFN
 # being an absolute path, so we need this.
@@ -479,6 +479,17 @@
                 safe_rmdir(ABSTFN + "/k")
                 safe_rmdir(ABSTFN)
 
+    def test_relpath(self):
+        currentdir = os.path.split(os.getcwd())[-1]
+        self.assertRaises(ValueError, posixpath.relpath, "")
+        self.assertEqual(posixpath.relpath("a"), "a")
+        self.assertEqual(posixpath.relpath(os.path.abspath("a")), "a")
+        self.assertEqual(posixpath.relpath("a/b"), "a/b")
+        self.assertEqual(posixpath.relpath("../a/b"), "../a/b")
+        self.assertEqual(posixpath.relpath("a", "../b"), "../"+currentdir+"/a")
+        self.assertEqual(posixpath.relpath("a/b", "../c"), "../"+currentdir+"/a/b")
+        self.assertEqual(posixpath.relpath("a", "b/c"), "../../a")
+
 def test_main():
     test_support.run_unittest(PosixPathTest)
 

Modified: python/trunk/Misc/ACKS
==============================================================================
--- python/trunk/Misc/ACKS	(original)
+++ python/trunk/Misc/ACKS	Fri Mar 16 23:16:08 2007
@@ -36,6 +36,7 @@
 Michael J. Barber
 Chris Barker
 Quentin Barnes
+Richard Barran
 Cesar Eduardo Barros
 Des Barry
 Ulf Bartelt

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Fri Mar 16 23:16:08 2007
@@ -191,6 +191,8 @@
   of those present. Also, it tries the Windows default browser before
   trying Mozilla variants.
 
+- Patch #1339796: add a relpath() function to os.path.
+
 - Patch #1681153: the wave module now closes a file object it opened if
   initialization failed.
 


More information about the Python-checkins mailing list