Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 156b361

Browse files
committed
Issue #19918: Fix PurePath.relative_to() under Windows.
1 parent 68816ef commit 156b361

3 files changed

Lines changed: 67 additions & 40 deletions

File tree

Lib/pathlib.py

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -780,27 +780,23 @@ def relative_to(self, *other):
780780
parts = self._parts
781781
drv = self._drv
782782
root = self._root
783-
if drv or root:
784-
if root:
785-
abs_parts = [drv, root] + parts[1:]
786-
else:
787-
abs_parts = [drv] + parts[1:]
783+
if root:
784+
abs_parts = [drv, root] + parts[1:]
788785
else:
789786
abs_parts = parts
790787
to_drv, to_root, to_parts = self._parse_args(other)
791-
if to_drv or to_root:
792-
if to_root:
793-
to_abs_parts = [to_drv, to_root] + to_parts[1:]
794-
else:
795-
to_abs_parts = [to_drv] + to_parts[1:]
788+
if to_root:
789+
to_abs_parts = [to_drv, to_root] + to_parts[1:]
796790
else:
797791
to_abs_parts = to_parts
798792
n = len(to_abs_parts)
799-
if n == 0 and (drv or root) or abs_parts[:n] != to_abs_parts:
793+
cf = self._flavour.casefold_parts
794+
if (root or drv) if n == 0 else cf(abs_parts[:n]) != cf(to_abs_parts):
800795
formatted = self._format_parsed_parts(to_drv, to_root, to_parts)
801796
raise ValueError("{!r} does not start with {!r}"
802797
.format(str(self), str(formatted)))
803-
return self._from_parsed_parts('', '', abs_parts[n:])
798+
return self._from_parsed_parts('', root if n == 1 else '',
799+
abs_parts[n:])
804800

805801
@property
806802
def parts(self):

Lib/test/test_pathlib.py

Lines changed: 57 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -536,9 +536,14 @@ def test_relative_to_common(self):
536536
P = self.cls
537537
p = P('a/b')
538538
self.assertRaises(TypeError, p.relative_to)
539+
self.assertRaises(TypeError, p.relative_to, b'a')
539540
self.assertEqual(p.relative_to(P()), P('a/b'))
541+
self.assertEqual(p.relative_to(''), P('a/b'))
540542
self.assertEqual(p.relative_to(P('a')), P('b'))
543+
self.assertEqual(p.relative_to('a'), P('b'))
544+
self.assertEqual(p.relative_to('a/'), P('b'))
541545
self.assertEqual(p.relative_to(P('a/b')), P())
546+
self.assertEqual(p.relative_to('a/b'), P())
542547
# With several args
543548
self.assertEqual(p.relative_to('a', 'b'), P())
544549
# Unrelated paths
@@ -548,13 +553,18 @@ def test_relative_to_common(self):
548553
self.assertRaises(ValueError, p.relative_to, P('/a'))
549554
p = P('/a/b')
550555
self.assertEqual(p.relative_to(P('/')), P('a/b'))
556+
self.assertEqual(p.relative_to('/'), P('a/b'))
551557
self.assertEqual(p.relative_to(P('/a')), P('b'))
558+
self.assertEqual(p.relative_to('/a'), P('b'))
559+
self.assertEqual(p.relative_to('/a/'), P('b'))
552560
self.assertEqual(p.relative_to(P('/a/b')), P())
561+
self.assertEqual(p.relative_to('/a/b'), P())
553562
# Unrelated paths
554563
self.assertRaises(ValueError, p.relative_to, P('/c'))
555564
self.assertRaises(ValueError, p.relative_to, P('/a/b/c'))
556565
self.assertRaises(ValueError, p.relative_to, P('/a/c'))
557566
self.assertRaises(ValueError, p.relative_to, P())
567+
self.assertRaises(ValueError, p.relative_to, '')
558568
self.assertRaises(ValueError, p.relative_to, P('a'))
559569

560570
def test_pickling_common(self):
@@ -917,42 +927,61 @@ def test_with_suffix(self):
917927

918928
def test_relative_to(self):
919929
P = self.cls
920-
p = P('c:a/b')
921-
self.assertEqual(p.relative_to(P('c:')), P('a/b'))
922-
self.assertEqual(p.relative_to(P('c:a')), P('b'))
923-
self.assertEqual(p.relative_to(P('c:a/b')), P())
930+
p = P('C:Foo/Bar')
931+
self.assertEqual(p.relative_to(P('c:')), P('Foo/Bar'))
932+
self.assertEqual(p.relative_to('c:'), P('Foo/Bar'))
933+
self.assertEqual(p.relative_to(P('c:foO')), P('Bar'))
934+
self.assertEqual(p.relative_to('c:foO'), P('Bar'))
935+
self.assertEqual(p.relative_to('c:foO/'), P('Bar'))
936+
self.assertEqual(p.relative_to(P('c:foO/baR')), P())
937+
self.assertEqual(p.relative_to('c:foO/baR'), P())
924938
# Unrelated paths
925939
self.assertRaises(ValueError, p.relative_to, P())
940+
self.assertRaises(ValueError, p.relative_to, '')
926941
self.assertRaises(ValueError, p.relative_to, P('d:'))
927-
self.assertRaises(ValueError, p.relative_to, P('a'))
928-
self.assertRaises(ValueError, p.relative_to, P('/a'))
929-
self.assertRaises(ValueError, p.relative_to, P('c:a/b/c'))
930-
self.assertRaises(ValueError, p.relative_to, P('c:a/c'))
931-
self.assertRaises(ValueError, p.relative_to, P('c:/a'))
932-
p = P('c:/a/b')
933-
self.assertEqual(p.relative_to(P('c:')), P('/a/b'))
934-
self.assertEqual(p.relative_to(P('c:/')), P('a/b'))
935-
self.assertEqual(p.relative_to(P('c:/a')), P('b'))
936-
self.assertEqual(p.relative_to(P('c:/a/b')), P())
942+
self.assertRaises(ValueError, p.relative_to, P('/'))
943+
self.assertRaises(ValueError, p.relative_to, P('Foo'))
944+
self.assertRaises(ValueError, p.relative_to, P('/Foo'))
945+
self.assertRaises(ValueError, p.relative_to, P('C:/Foo'))
946+
self.assertRaises(ValueError, p.relative_to, P('C:Foo/Bar/Baz'))
947+
self.assertRaises(ValueError, p.relative_to, P('C:Foo/Baz'))
948+
p = P('C:/Foo/Bar')
949+
self.assertEqual(p.relative_to(P('c:')), P('/Foo/Bar'))
950+
self.assertEqual(p.relative_to('c:'), P('/Foo/Bar'))
951+
self.assertEqual(str(p.relative_to(P('c:'))), '\\Foo\\Bar')
952+
self.assertEqual(str(p.relative_to('c:')), '\\Foo\\Bar')
953+
self.assertEqual(p.relative_to(P('c:/')), P('Foo/Bar'))
954+
self.assertEqual(p.relative_to('c:/'), P('Foo/Bar'))
955+
self.assertEqual(p.relative_to(P('c:/foO')), P('Bar'))
956+
self.assertEqual(p.relative_to('c:/foO'), P('Bar'))
957+
self.assertEqual(p.relative_to('c:/foO/'), P('Bar'))
958+
self.assertEqual(p.relative_to(P('c:/foO/baR')), P())
959+
self.assertEqual(p.relative_to('c:/foO/baR'), P())
937960
# Unrelated paths
938-
self.assertRaises(ValueError, p.relative_to, P('c:/c'))
939-
self.assertRaises(ValueError, p.relative_to, P('c:/a/b/c'))
940-
self.assertRaises(ValueError, p.relative_to, P('c:/a/c'))
941-
self.assertRaises(ValueError, p.relative_to, P('c:a'))
961+
self.assertRaises(ValueError, p.relative_to, P('C:/Baz'))
962+
self.assertRaises(ValueError, p.relative_to, P('C:/Foo/Bar/Baz'))
963+
self.assertRaises(ValueError, p.relative_to, P('C:/Foo/Baz'))
964+
self.assertRaises(ValueError, p.relative_to, P('C:Foo'))
942965
self.assertRaises(ValueError, p.relative_to, P('d:'))
943966
self.assertRaises(ValueError, p.relative_to, P('d:/'))
944-
self.assertRaises(ValueError, p.relative_to, P('/a'))
945-
self.assertRaises(ValueError, p.relative_to, P('//c/a'))
967+
self.assertRaises(ValueError, p.relative_to, P('/'))
968+
self.assertRaises(ValueError, p.relative_to, P('/Foo'))
969+
self.assertRaises(ValueError, p.relative_to, P('//C/Foo'))
946970
# UNC paths
947-
p = P('//a/b/c/d')
948-
self.assertEqual(p.relative_to(P('//a/b')), P('c/d'))
949-
self.assertEqual(p.relative_to(P('//a/b/c')), P('d'))
950-
self.assertEqual(p.relative_to(P('//a/b/c/d')), P())
971+
p = P('//Server/Share/Foo/Bar')
972+
self.assertEqual(p.relative_to(P('//sErver/sHare')), P('Foo/Bar'))
973+
self.assertEqual(p.relative_to('//sErver/sHare'), P('Foo/Bar'))
974+
self.assertEqual(p.relative_to('//sErver/sHare/'), P('Foo/Bar'))
975+
self.assertEqual(p.relative_to(P('//sErver/sHare/Foo')), P('Bar'))
976+
self.assertEqual(p.relative_to('//sErver/sHare/Foo'), P('Bar'))
977+
self.assertEqual(p.relative_to('//sErver/sHare/Foo/'), P('Bar'))
978+
self.assertEqual(p.relative_to(P('//sErver/sHare/Foo/Bar')), P())
979+
self.assertEqual(p.relative_to('//sErver/sHare/Foo/Bar'), P())
951980
# Unrelated paths
952-
self.assertRaises(ValueError, p.relative_to, P('/a/b/c'))
953-
self.assertRaises(ValueError, p.relative_to, P('c:/a/b/c'))
954-
self.assertRaises(ValueError, p.relative_to, P('//z/b/c'))
955-
self.assertRaises(ValueError, p.relative_to, P('//a/z/c'))
981+
self.assertRaises(ValueError, p.relative_to, P('/Server/Share/Foo'))
982+
self.assertRaises(ValueError, p.relative_to, P('c:/Server/Share/Foo'))
983+
self.assertRaises(ValueError, p.relative_to, P('//z/Share/Foo'))
984+
self.assertRaises(ValueError, p.relative_to, P('//Server/z/Foo'))
956985

957986
def test_is_absolute(self):
958987
P = self.cls

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ Core and Builtins
4444
Library
4545
-------
4646

47+
- Issue #19918: Fix PurePath.relative_to() under Windows.
48+
4749
- Issue #19422: Explicitly disallow non-SOCK_STREAM sockets in the ssl
4850
module, rather than silently let them emit clear text data.
4951

0 commit comments

Comments
 (0)