classification
Title: Re: Allow Path.relative_to() to accept non-ancestor paths
Type: enhancement Stage: resolved
Components: Library (Lib) Versions: Python 3.4
process
Status: closed Resolution: duplicate
Dependencies: Superseder: pathlib's relative_to should behave like os.path.relpath
View: 40358
Assigned To: Nosy List: Japanuspus, aukbten, javawizard, pitrou
Priority: normal Keywords:

Created on 2013-12-18 06:10 by javawizard, last changed 2021-06-23 11:10 by Antony.Lee. This issue is now closed.

Messages (6)
msg206497 - (view) Author: Alexander Boyd (javawizard) Date: 2013-12-18 06:10
pathlib.Path.relative_to() blows up when given a path that's not an ancestor of the path on which relative_to is being called:

>>> pathlib.Path("/usr/bin").relative_to("/etc")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pathlib.py", line 822, in relative_to
    .format(str(self), str(formatted)))
ValueError: '/usr/bin' does not start with '/etc'

The equivalent with posixpath.relpath (or ntpath.relpath) works just fine:

>>> posixpath.relpath("/usr/bin", "/etc")
'../usr/bin'

It'd be nice if Path.relative_to supported this type of usage.
msg206499 - (view) Author: Anurag Kulkarni (aukbten) Date: 2013-12-18 06:55
Hey! 
A few changes are required to accomplish what you seek, but results could be severe. Path.relative_to() should return an exception if relative path is not part of the original path. However, I have got a solution for that. I am not that familiar with python and I need you to give me some time. I hope you would acknowledge my efforts.
Regards
msg206535 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-12-18 16:07
That's by design. If /etc is a symlink to e.g. /mnt/etc, the proposed result is wrong.
msg207810 - (view) Author: Alexander Boyd (javawizard) Date: 2014-01-10 00:28
Then perhaps the docstring of relative_to could note this (like relpath does), or a separate method that's explicitly not symlink safe created.

Or better yet, what about a function that does (or at least tries to) give the correct answer in the face of symlinks?
msg262305 - (view) Author: Antony Lee (Antony.Lee) * Date: 2016-03-23 20:29
Kindly bumping the issue.
I'd suggest overriding `PurePath.relative_to` in the `Path` class, to something like `PurePath.relative_to(self, other, *, allow_ancestor=False): ...`, which would resolve each ancestor of `self` successively to check whether it is also an ancestor of `other`, so that symlinks would be handled correctly.
msg396390 - (view) Author: Janus (Japanuspus) Date: 2021-06-23 08:59
This issue is being addressed in #40358 which has open PR for v3.11
History
Date User Action Args
2021-06-23 11:10:25Antony.Leesetnosy: - Antony.Lee
2021-06-23 10:41:12serhiy.storchakasetstatus: open -> closed
superseder: pathlib's relative_to should behave like os.path.relpath
resolution: duplicate
stage: resolved
2021-06-23 08:59:16Japanuspussetnosy: + Japanuspus
messages: + msg396390
2016-03-23 20:29:30Antony.Leesetnosy: + Antony.Lee
messages: + msg262305
2014-01-10 00:28:38javawizardsetmessages: + msg207810
2013-12-18 16:07:27pitrousetmessages: + msg206535
2013-12-18 06:55:45aukbtensetnosy: + aukbten

messages: + msg206499
title: Allow Path.relative_to() to accept non-ancestor paths -> Re: Allow Path.relative_to() to accept non-ancestor paths
2013-12-18 06:10:11javawizardcreate