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

Skip to content

Commit 82642a0

Browse files
shihai1991pitrou
authored andcommitted
bpo-37689: add Path.is_relative_to() method (GH-14982)
1 parent 8a784af commit 82642a0

File tree

4 files changed

+111
-1
lines changed

4 files changed

+111
-1
lines changed

Doc/library/pathlib.rst

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ Methods and properties
273273

274274
.. testsetup::
275275

276-
from pathlib import PurePosixPath, PureWindowsPath
276+
from pathlib import PurePath, PurePosixPath, PureWindowsPath
277277

278278
Pure paths provide the following methods and properties:
279279

@@ -462,6 +462,19 @@ Pure paths provide the following methods and properties:
462462
True
463463

464464

465+
.. method:: PurePath.is_relative_to(*other)
466+
467+
Return whether or not this path is relative to the *other* path.
468+
469+
>>> p = PurePath('/etc/passwd')
470+
>>> p.is_relative_to('/etc')
471+
True
472+
>>> p.is_relative_to('/usr')
473+
False
474+
475+
.. versionadded:: 3.9
476+
477+
465478
.. method:: PurePath.is_reserved()
466479

467480
With :class:`PureWindowsPath`, return ``True`` if the path is considered

Lib/pathlib.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,15 @@ def relative_to(self, *other):
886886
return self._from_parsed_parts('', root if n == 1 else '',
887887
abs_parts[n:])
888888

889+
def is_relative_to(self, *other):
890+
"""Return True if the path is relative to another path or False.
891+
"""
892+
try:
893+
self.relative_to(*other)
894+
return True
895+
except ValueError:
896+
return False
897+
889898
@property
890899
def parts(self):
891900
"""An object providing sequence-like access to the

Lib/test/test_pathlib.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,40 @@ def test_relative_to_common(self):
619619
self.assertRaises(ValueError, p.relative_to, '')
620620
self.assertRaises(ValueError, p.relative_to, P('a'))
621621

622+
def test_is_relative_to_common(self):
623+
P = self.cls
624+
p = P('a/b')
625+
self.assertRaises(TypeError, p.is_relative_to)
626+
self.assertRaises(TypeError, p.is_relative_to, b'a')
627+
self.assertTrue(p.is_relative_to(P()))
628+
self.assertTrue(p.is_relative_to(''))
629+
self.assertTrue(p.is_relative_to(P('a')))
630+
self.assertTrue(p.is_relative_to('a/'))
631+
self.assertTrue(p.is_relative_to(P('a/b')))
632+
self.assertTrue(p.is_relative_to('a/b'))
633+
# With several args.
634+
self.assertTrue(p.is_relative_to('a', 'b'))
635+
# Unrelated paths.
636+
self.assertFalse(p.is_relative_to(P('c')))
637+
self.assertFalse(p.is_relative_to(P('a/b/c')))
638+
self.assertFalse(p.is_relative_to(P('a/c')))
639+
self.assertFalse(p.is_relative_to(P('/a')))
640+
p = P('/a/b')
641+
self.assertTrue(p.is_relative_to(P('/')))
642+
self.assertTrue(p.is_relative_to('/'))
643+
self.assertTrue(p.is_relative_to(P('/a')))
644+
self.assertTrue(p.is_relative_to('/a'))
645+
self.assertTrue(p.is_relative_to('/a/'))
646+
self.assertTrue(p.is_relative_to(P('/a/b')))
647+
self.assertTrue(p.is_relative_to('/a/b'))
648+
# Unrelated paths.
649+
self.assertFalse(p.is_relative_to(P('/c')))
650+
self.assertFalse(p.is_relative_to(P('/a/b/c')))
651+
self.assertFalse(p.is_relative_to(P('/a/c')))
652+
self.assertFalse(p.is_relative_to(P()))
653+
self.assertFalse(p.is_relative_to(''))
654+
self.assertFalse(p.is_relative_to(P('a')))
655+
622656
def test_pickling_common(self):
623657
P = self.cls
624658
p = P('/a/b')
@@ -1062,6 +1096,59 @@ def test_relative_to(self):
10621096
self.assertRaises(ValueError, p.relative_to, P('//z/Share/Foo'))
10631097
self.assertRaises(ValueError, p.relative_to, P('//Server/z/Foo'))
10641098

1099+
def test_is_relative_to(self):
1100+
P = self.cls
1101+
p = P('C:Foo/Bar')
1102+
self.assertTrue(p.is_relative_to(P('c:')))
1103+
self.assertTrue(p.is_relative_to('c:'))
1104+
self.assertTrue(p.is_relative_to(P('c:foO')))
1105+
self.assertTrue(p.is_relative_to('c:foO'))
1106+
self.assertTrue(p.is_relative_to('c:foO/'))
1107+
self.assertTrue(p.is_relative_to(P('c:foO/baR')))
1108+
self.assertTrue(p.is_relative_to('c:foO/baR'))
1109+
# Unrelated paths.
1110+
self.assertFalse(p.is_relative_to(P()))
1111+
self.assertFalse(p.is_relative_to(''))
1112+
self.assertFalse(p.is_relative_to(P('d:')))
1113+
self.assertFalse(p.is_relative_to(P('/')))
1114+
self.assertFalse(p.is_relative_to(P('Foo')))
1115+
self.assertFalse(p.is_relative_to(P('/Foo')))
1116+
self.assertFalse(p.is_relative_to(P('C:/Foo')))
1117+
self.assertFalse(p.is_relative_to(P('C:Foo/Bar/Baz')))
1118+
self.assertFalse(p.is_relative_to(P('C:Foo/Baz')))
1119+
p = P('C:/Foo/Bar')
1120+
self.assertTrue(p.is_relative_to('c:'))
1121+
self.assertTrue(p.is_relative_to(P('c:/')))
1122+
self.assertTrue(p.is_relative_to(P('c:/foO')))
1123+
self.assertTrue(p.is_relative_to('c:/foO/'))
1124+
self.assertTrue(p.is_relative_to(P('c:/foO/baR')))
1125+
self.assertTrue(p.is_relative_to('c:/foO/baR'))
1126+
# Unrelated paths.
1127+
self.assertFalse(p.is_relative_to(P('C:/Baz')))
1128+
self.assertFalse(p.is_relative_to(P('C:/Foo/Bar/Baz')))
1129+
self.assertFalse(p.is_relative_to(P('C:/Foo/Baz')))
1130+
self.assertFalse(p.is_relative_to(P('C:Foo')))
1131+
self.assertFalse(p.is_relative_to(P('d:')))
1132+
self.assertFalse(p.is_relative_to(P('d:/')))
1133+
self.assertFalse(p.is_relative_to(P('/')))
1134+
self.assertFalse(p.is_relative_to(P('/Foo')))
1135+
self.assertFalse(p.is_relative_to(P('//C/Foo')))
1136+
# UNC paths.
1137+
p = P('//Server/Share/Foo/Bar')
1138+
self.assertTrue(p.is_relative_to(P('//sErver/sHare')))
1139+
self.assertTrue(p.is_relative_to('//sErver/sHare'))
1140+
self.assertTrue(p.is_relative_to('//sErver/sHare/'))
1141+
self.assertTrue(p.is_relative_to(P('//sErver/sHare/Foo')))
1142+
self.assertTrue(p.is_relative_to('//sErver/sHare/Foo'))
1143+
self.assertTrue(p.is_relative_to('//sErver/sHare/Foo/'))
1144+
self.assertTrue(p.is_relative_to(P('//sErver/sHare/Foo/Bar')))
1145+
self.assertTrue(p.is_relative_to('//sErver/sHare/Foo/Bar'))
1146+
# Unrelated paths.
1147+
self.assertFalse(p.is_relative_to(P('/Server/Share/Foo')))
1148+
self.assertFalse(p.is_relative_to(P('c:/Server/Share/Foo')))
1149+
self.assertFalse(p.is_relative_to(P('//z/Share/Foo')))
1150+
self.assertFalse(p.is_relative_to(P('//Server/z/Foo')))
1151+
10651152
def test_is_absolute(self):
10661153
P = self.cls
10671154
# Under NT, only paths with both a drive and a root are absolute.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add :meth:`is_relative_to` in :class:`PurePath` to determine whether or not one path is relative to another.

0 commit comments

Comments
 (0)