mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	Patch 1339796: add a relpath() function to os.path.
This commit is contained in:
		
							parent
							
								
									6de691d78c
								
							
						
					
					
						commit
						6f187743ff
					
				
					 7 changed files with 77 additions and 3 deletions
				
			
		|  | @ -189,6 +189,15 @@ operating system). | ||||||
| \versionadded{2.2} | \versionadded{2.2} | ||||||
| \end{funcdesc} | \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} | \begin{funcdesc}{samefile}{path1, path2} | ||||||
| Return \code{True} if both pathname arguments refer to the same file or | Return \code{True} if both pathname arguments refer to the same file or | ||||||
| directory (as indicated by device number and i-node number). | directory (as indicated by device number and i-node number). | ||||||
|  |  | ||||||
|  | @ -16,7 +16,7 @@ | ||||||
|            "getatime","getctime", "islink","exists","lexists","isdir","isfile", |            "getatime","getctime", "islink","exists","lexists","isdir","isfile", | ||||||
|            "ismount","walk","expanduser","expandvars","normpath","abspath", |            "ismount","walk","expanduser","expandvars","normpath","abspath", | ||||||
|            "splitunc","curdir","pardir","sep","pathsep","defpath","altsep", |            "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 | # strings representing various path-related bits and pieces | ||||||
| curdir = '.' | curdir = '.' | ||||||
|  | @ -465,3 +465,29 @@ def abspath(path): | ||||||
| # Win9x family and earlier have no Unicode filename support. | # Win9x family and earlier have no Unicode filename support. | ||||||
| supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and | supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and | ||||||
|                               sys.getwindowsversion()[3] >= 2) |                               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) | ||||||
|  |  | ||||||
|  | @ -21,7 +21,7 @@ | ||||||
|            "ismount","walk","expanduser","expandvars","normpath","abspath", |            "ismount","walk","expanduser","expandvars","normpath","abspath", | ||||||
|            "samefile","sameopenfile","samestat", |            "samefile","sameopenfile","samestat", | ||||||
|            "curdir","pardir","sep","pathsep","defpath","altsep","extsep", |            "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 | # strings representing various path-related bits and pieces | ||||||
| curdir = '.' | curdir = '.' | ||||||
|  | @ -382,3 +382,18 @@ def _resolve_link(path): | ||||||
|     return path |     return path | ||||||
| 
 | 
 | ||||||
| supports_unicode_filenames = False | 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) | ||||||
|  |  | ||||||
|  | @ -157,6 +157,16 @@ def tester(fn, wantResult): | ||||||
| else: | else: | ||||||
|     tester('ntpath.abspath("C:\\")', "C:\\") |     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: | if errors: | ||||||
|     raise TestFailed(str(errors) + " errors.") |     raise TestFailed(str(errors) + " errors.") | ||||||
| elif verbose: | elif verbose: | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| from test import test_support | from test import test_support | ||||||
| 
 | 
 | ||||||
| import posixpath, os | 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 | # An absolute path to a temporary filename for testing. We can't rely on TESTFN | ||||||
| # being an absolute path, so we need this. | # being an absolute path, so we need this. | ||||||
|  | @ -479,6 +479,17 @@ def test_realpath_resolve_first(self): | ||||||
|                 safe_rmdir(ABSTFN + "/k") |                 safe_rmdir(ABSTFN + "/k") | ||||||
|                 safe_rmdir(ABSTFN) |                 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(): | def test_main(): | ||||||
|     test_support.run_unittest(PosixPathTest) |     test_support.run_unittest(PosixPathTest) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -36,6 +36,7 @@ Luigi Ballabio | ||||||
| Michael J. Barber | Michael J. Barber | ||||||
| Chris Barker | Chris Barker | ||||||
| Quentin Barnes | Quentin Barnes | ||||||
|  | Richard Barran | ||||||
| Cesar Eduardo Barros | Cesar Eduardo Barros | ||||||
| Des Barry | Des Barry | ||||||
| Ulf Bartelt | Ulf Bartelt | ||||||
|  |  | ||||||
|  | @ -191,6 +191,8 @@ Library | ||||||
|   of those present. Also, it tries the Windows default browser before |   of those present. Also, it tries the Windows default browser before | ||||||
|   trying Mozilla variants. |   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 | - Patch #1681153: the wave module now closes a file object it opened if | ||||||
|   initialization failed. |   initialization failed. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Collin Winter
						Collin Winter