gh-78707: deprecate passing >1 argument to PurePath.[is_]relative_to() (GH-94469)

This brings `relative_to()` and `is_relative_to()` more in line with other pathlib methods like `rename()` and `symlink_to()`.

Resolves #78707.
This commit is contained in:
Barney Gale 2022-12-17 00:14:27 +00:00 committed by GitHub
parent 432117cd1f
commit 5a991da329
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 14 deletions

View file

@ -490,7 +490,7 @@ Pure paths provide the following methods and properties:
True
.. method:: PurePath.is_relative_to(*other)
.. method:: PurePath.is_relative_to(other)
Return whether or not this path is relative to the *other* path.
@ -502,6 +502,10 @@ Pure paths provide the following methods and properties:
.. versionadded:: 3.9
.. deprecated-removed:: 3.12 3.14
Passing additional arguments is deprecated; if supplied, they are joined
with *other*.
.. method:: PurePath.is_reserved()
@ -564,7 +568,7 @@ Pure paths provide the following methods and properties:
True
.. method:: PurePath.relative_to(*other, walk_up=False)
.. method:: PurePath.relative_to(other, walk_up=False)
Compute a version of this path relative to the path represented by
*other*. If it's impossible, :exc:`ValueError` is raised::
@ -581,7 +585,7 @@ Pure paths provide the following methods and properties:
raise ValueError(error_message.format(str(self), str(formatted)))
ValueError: '/etc/passwd' is not in the subpath of '/usr' OR one path is relative and the other is absolute.
When *walk_up* is False (the default), the path must start with *other*.
When *walk_up* is False (the default), the path must start with *other*.
When the argument is True, ``..`` entries may be added to form the
relative path. In all other cases, such as the paths referencing
different drives, :exc:`ValueError` is raised.::
@ -605,6 +609,10 @@ When *walk_up* is False (the default), the path must start with *other*.
.. versionadded:: 3.12
The *walk_up* argument (old behavior is the same as ``walk_up=False``).
.. deprecated-removed:: 3.12 3.14
Passing additional positional arguments is deprecated; if supplied,
they are joined with *other*.
.. method:: PurePath.with_name(name)

View file

@ -624,7 +624,7 @@ class PurePath(object):
return self._from_parsed_parts(self._drv, self._root,
self._parts[:-1] + [name])
def relative_to(self, *other, walk_up=False):
def relative_to(self, other, /, *_deprecated, walk_up=False):
"""Return the relative path to another path identified by the passed
arguments. If the operation is not possible (because this is not
related to the other path), raise ValueError.
@ -632,10 +632,14 @@ class PurePath(object):
The *walk_up* parameter controls whether `..` may be used to resolve
the path.
"""
if not other:
raise TypeError("need at least one argument")
if _deprecated:
msg = ("support for supplying more than one positional argument "
"to pathlib.PurePath.relative_to() is deprecated and "
"scheduled for removal in Python {remove}")
warnings._deprecated("pathlib.PurePath.relative_to(*args)", msg,
remove=(3, 14))
path_cls = type(self)
other = path_cls(*other)
other = path_cls(other, *_deprecated)
for step, path in enumerate([other] + list(other.parents)):
if self.is_relative_to(path):
break
@ -646,12 +650,16 @@ class PurePath(object):
parts = ('..',) * step + self.parts[len(path.parts):]
return path_cls(*parts)
def is_relative_to(self, *other):
def is_relative_to(self, other, /, *_deprecated):
"""Return True if the path is relative to another path or False.
"""
if not other:
raise TypeError("need at least one argument")
other = type(self)(*other)
if _deprecated:
msg = ("support for supplying more than one argument to "
"pathlib.PurePath.is_relative_to() is deprecated and "
"scheduled for removal in Python {remove}")
warnings._deprecated("pathlib.PurePath.is_relative_to(*args)",
msg, remove=(3, 14))
other = type(self)(other, *_deprecated)
return other == self or other in self.parents
@property

View file

@ -654,8 +654,9 @@ class _BasePurePathTest(object):
self.assertEqual(p.relative_to(P('c'), walk_up=True), P('../a/b'))
self.assertEqual(p.relative_to('c', walk_up=True), P('../a/b'))
# With several args.
self.assertEqual(p.relative_to('a', 'b'), P())
self.assertEqual(p.relative_to('a', 'b', walk_up=True), P())
with self.assertWarns(DeprecationWarning):
p.relative_to('a', 'b')
p.relative_to('a', 'b', walk_up=True)
# Unrelated paths.
self.assertRaises(ValueError, p.relative_to, P('c'))
self.assertRaises(ValueError, p.relative_to, P('a/b/c'))
@ -706,7 +707,8 @@ class _BasePurePathTest(object):
self.assertTrue(p.is_relative_to(P('a/b')))
self.assertTrue(p.is_relative_to('a/b'))
# With several args.
self.assertTrue(p.is_relative_to('a', 'b'))
with self.assertWarns(DeprecationWarning):
p.is_relative_to('a', 'b')
# Unrelated paths.
self.assertFalse(p.is_relative_to(P('c')))
self.assertFalse(p.is_relative_to(P('a/b/c')))

View file

@ -0,0 +1,3 @@
Deprecate passing more than one positional argument to
:meth:`pathlib.PurePath.relative_to` and
:meth:`~pathlib.PurePath.is_relative_to`.