diff -r d5536c06a082 Lib/ntpath.py --- a/Lib/ntpath.py Fri Jul 05 01:40:52 2013 +0200 +++ b/Lib/ntpath.py Sun Jul 07 02:18:19 2013 +0200 @@ -620,6 +620,12 @@ start_list = [x for x in start_rest.split(sep) if x] path_list = [x for x in path_rest.split(sep) if x] # Work out how much of the filepath is shared by start and path. + + has_extension = start_list and "." in str(start_list[-1]) + if isfile(start_abs) or has_extension: + # A file (not directory) is given as an argument for 'start'. + start_list = start_list[:-1] + i = 0 for e1, e2 in zip(start_list, path_list): if normcase(e1) != normcase(e2): diff -r d5536c06a082 Lib/posixpath.py --- a/Lib/posixpath.py Fri Jul 05 01:40:52 2013 +0200 +++ b/Lib/posixpath.py Sun Jul 07 02:18:19 2013 +0200 @@ -439,8 +439,15 @@ if start is None: start = curdir - 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_abs = abspath(start) + path_abs = abspath(path) + start_list = [x for x in start_abs.split(sep) if x] + path_list = [x for x in path_abs.split(sep) if x] + + has_extension = start_list and "." in str(start_list[-1]) + if isfile(start) or has_extension: + # A file (not directory) is given as an argument for 'start'. + start_list = start_list[:-1] # Work out how much of the filepath is shared by start and path. i = len(commonprefix([start_list, path_list])) diff -r d5536c06a082 Lib/test/test_ntpath.py --- a/Lib/test/test_ntpath.py Fri Jul 05 01:40:52 2013 +0200 +++ b/Lib/test/test_ntpath.py Sun Jul 07 02:18:19 2013 +0200 @@ -221,6 +221,7 @@ pass def test_relpath(self): + import unittest.mock currentdir = os.path.split(os.getcwd())[-1] tester('ntpath.relpath("a")', 'a') tester('ntpath.relpath(os.path.abspath("a"))', 'a') @@ -242,6 +243,13 @@ tester('ntpath.relpath("/a", "/a")', '.') tester('ntpath.relpath("/a/b", "/a/b")', '.') tester('ntpath.relpath("c:/foo", "C:/FOO")', '.') + tester('ntpath.relpath("bar/bat", "foo.ext")', 'bar\\bat') + with unittest.mock.patch('ntpath.isfile') as isfile: + isfile.return_value = False; + tester('ntpath.relpath("bar/bat", "foo")', '..\\bar\\bat') + with unittest.mock.patch('ntpath.isfile') as isfile: + isfile.return_value = True; + tester('ntpath.relpath("bar/bat", "foo")', 'bar\\bat') def test_sameopenfile(self): with TemporaryFile() as tf1, TemporaryFile() as tf2: diff -r d5536c06a082 Lib/test/test_posixpath.py --- a/Lib/test/test_posixpath.py Fri Jul 05 01:40:52 2013 +0200 +++ b/Lib/test/test_posixpath.py Sun Jul 07 02:18:19 2013 +0200 @@ -483,6 +483,7 @@ safe_rmdir(ABSTFN) def test_relpath(self): + import unittest.mock (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar") try: curdir = os.path.split(os.getcwd())[-1] @@ -505,6 +506,13 @@ self.assertEqual(posixpath.relpath("/", "/"), '.') self.assertEqual(posixpath.relpath("/a", "/a"), '.') self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.') + self.assertEqual(posixpath.relpath("foo/bar", "bat.ext"), "foo/bar") + with unittest.mock.patch('posixpath.isfile') as isfile: + isfile.return_value = False; + self.assertEqual(posixpath.relpath("foo/bar", "bat"), "../foo/bar") + with unittest.mock.patch('posixpath.isfile') as isfile: + isfile.return_value = True; + self.assertEqual(posixpath.relpath("foo/bar", "bat"), "foo/bar") finally: os.getcwd = real_getcwd @@ -532,6 +540,14 @@ self.assertEqual(posixpath.relpath(b"/", b"/"), b'.') self.assertEqual(posixpath.relpath(b"/a", b"/a"), b'.') self.assertEqual(posixpath.relpath(b"/a/b", b"/a/b"), b'.') + self.assertEqual(posixpath.relpath(b"foo/bar", b"bat.ext"), b"foo/bar") + with unittest.mock.patch('posixpath.isfile') as isfile: + isfile.return_value = False; + self.assertEqual(posixpath.relpath(b"foo/bar", b"bat"), b"../foo/bar") + with unittest.mock.patch('posixpath.isfile') as isfile: + isfile.return_value = True; + self.assertEqual(posixpath.relpath(b"foo/bar", b"bat"), b"foo/bar") + self.assertRaises(TypeError, posixpath.relpath, b"bytes", "str") self.assertRaises(TypeError, posixpath.relpath, "str", b"bytes")