Index: ntpath.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/ntpath.py,v retrieving revision 1.63 diff -c -r1.63 ntpath.py *** ntpath.py 22 Aug 2005 18:01:03 -0000 1.63 --- ntpath.py 27 Oct 2005 17:15:30 -0000 *************** *** 14,20 **** "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"] # strings representing various path-related bits and pieces curdir = '.' --- 14,20 ---- "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","relpath"] # strings representing various path-related bits and pieces curdir = '.' *************** *** 508,510 **** --- 508,536 ---- # 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 (unc_path and not unc_start) or (not unc_path and 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 os.path.join(*rel_list) Index: posixpath.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/posixpath.py,v retrieving revision 1.75 diff -c -r1.75 posixpath.py *** posixpath.py 22 Aug 2005 18:01:03 -0000 1.75 --- posixpath.py 27 Oct 2005 17:15:31 -0000 *************** *** 19,25 **** "ismount","walk","expanduser","expandvars","normpath","abspath", "samefile","sameopenfile","samestat", "curdir","pardir","sep","pathsep","defpath","altsep","extsep", ! "devnull","realpath","supports_unicode_filenames"] # strings representing various path-related bits and pieces curdir = '.' --- 19,25 ---- "ismount","walk","expanduser","expandvars","normpath","abspath", "samefile","sameopenfile","samestat", "curdir","pardir","sep","pathsep","defpath","altsep","extsep", ! "devnull","realpath","supports_unicode_filenames","relpath"] # strings representing various path-related bits and pieces curdir = '.' *************** *** 452,454 **** --- 452,473 ---- 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. + for i in range(min(len(start_list), len(path_list))): + if start_list[i] <> path_list[i]: + break + else: + i+=1 + + rel_list = [pardir] * (len(start_list)-i) + path_list[i:] + return os.path.join(*rel_list) Index: test/test_ntpath.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_ntpath.py,v retrieving revision 1.19 diff -c -r1.19 test_ntpath.py *** test/test_ntpath.py 10 Jul 2004 20:42:22 -0000 1.19 --- test/test_ntpath.py 27 Oct 2005 17:15:33 -0000 *************** *** 127,132 **** --- 127,142 ---- 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: Index: test/test_posixpath.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_posixpath.py,v retrieving revision 1.14 diff -c -r1.14 test_posixpath.py *** test/test_posixpath.py 3 Jun 2005 22:40:28 -0000 1.14 --- test/test_posixpath.py 27 Oct 2005 17:15:34 -0000 *************** *** 2,8 **** from test import test_support import posixpath, os ! from posixpath import realpath, abspath, join, dirname, basename # An absolute path to a temporary filename for testing. We can't rely on TESTFN # being an absolute path, so we need this. --- 2,8 ---- from test import test_support import posixpath, os ! 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. *************** *** 508,513 **** --- 508,524 ---- def safe_rmdir(self, dirname): self.pass_os_error(os.rmdir, dirname) + 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)