Skip to content

Commit

Permalink
gh-105002: [pathlib] Fix relative_to with walk_up=True using ".." (#1…
Browse files Browse the repository at this point in the history
…07014)

It makes sense to raise an Error because ".." can not
be resolved and the current working directory is unknown.
  • Loading branch information
kukovecz committed Jul 26, 2023
1 parent 6d5b6e7 commit e7e6e4b
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 2 deletions.
6 changes: 4 additions & 2 deletions Lib/pathlib.py
Expand Up @@ -633,10 +633,12 @@ def relative_to(self, other, /, *_deprecated, walk_up=False):
for step, path in enumerate([other] + list(other.parents)):
if self.is_relative_to(path):
break
elif not walk_up:
raise ValueError(f"{str(self)!r} is not in the subpath of {str(other)!r}")
elif path.name == '..':
raise ValueError(f"'..' segment in {str(other)!r} cannot be walked")
else:
raise ValueError(f"{str(self)!r} and {str(other)!r} have different anchors")
if step and not walk_up:
raise ValueError(f"{str(self)!r} is not in the subpath of {str(other)!r}")
parts = ['..'] * step + self._tail[len(path._tail):]
return self.with_segments(*parts)

Expand Down
12 changes: 12 additions & 0 deletions Lib/test/test_pathlib.py
Expand Up @@ -693,8 +693,14 @@ def test_relative_to_common(self):
self.assertRaises(ValueError, p.relative_to, P('a/b/c'))
self.assertRaises(ValueError, p.relative_to, P('a/c'))
self.assertRaises(ValueError, p.relative_to, P('/a'))
self.assertRaises(ValueError, p.relative_to, P("../a"))
self.assertRaises(ValueError, p.relative_to, P("a/.."))
self.assertRaises(ValueError, p.relative_to, P("/a/.."))
self.assertRaises(ValueError, p.relative_to, P('/'), walk_up=True)
self.assertRaises(ValueError, p.relative_to, P('/a'), walk_up=True)
self.assertRaises(ValueError, p.relative_to, P("../a"), walk_up=True)
self.assertRaises(ValueError, p.relative_to, P("a/.."), walk_up=True)
self.assertRaises(ValueError, p.relative_to, P("/a/.."), walk_up=True)
p = P('/a/b')
self.assertEqual(p.relative_to(P('/')), P('a/b'))
self.assertEqual(p.relative_to('/'), P('a/b'))
Expand Down Expand Up @@ -723,8 +729,14 @@ def test_relative_to_common(self):
self.assertRaises(ValueError, p.relative_to, P())
self.assertRaises(ValueError, p.relative_to, '')
self.assertRaises(ValueError, p.relative_to, P('a'))
self.assertRaises(ValueError, p.relative_to, P("../a"))
self.assertRaises(ValueError, p.relative_to, P("a/.."))
self.assertRaises(ValueError, p.relative_to, P("/a/.."))
self.assertRaises(ValueError, p.relative_to, P(''), walk_up=True)
self.assertRaises(ValueError, p.relative_to, P('a'), walk_up=True)
self.assertRaises(ValueError, p.relative_to, P("../a"), walk_up=True)
self.assertRaises(ValueError, p.relative_to, P("a/.."), walk_up=True)
self.assertRaises(ValueError, p.relative_to, P("/a/.."), walk_up=True)

def test_is_relative_to_common(self):
P = self.cls
Expand Down
@@ -0,0 +1,3 @@
Fix invalid result from :meth:`PurePath.relative_to` method when attempting to walk
a "``..``" segment in *other* with *walk_up* enabled. A :exc:`ValueError` exception
is now raised in this case.

0 comments on commit e7e6e4b

Please sign in to comment.