-
-
Notifications
You must be signed in to change notification settings - Fork 31.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
pathlib's relative_to should behave like os.path.relpath #84538
Comments
Can we improve pathlib.relative_to(other) so that it handles the case of a path not being a direct child of other, like os.path.relpath? For example: At the moment it just raises an exception. |
The current behaviour is by design. I would not mind adding an option to control it, though. If you are new to Python development and want to submit a patch or PR, I recommend reading the Developer's Guide: |
Thanks for your answer. Yeah, I'm new, I'm reading the guide, sorry for any Ok, an option would be great as well, a simple True/False switch? Any On Wed, Apr 22, 2020 at 8:18 PM Antoine Pitrou <report@bugs.python.org>
|
Note that the implementation of relpath is pure and thus assumes it's working with existing, resolved paths (i.e. "the filesystem is not accessed to confirm the existence or nature of path or start"). For example: >>> os.path.relpath('/some/thing', '/symlink')
'../some/thing' If "symlink" targets "/spam/eggs/foo", then the resolved path would be "/spam/eggs/some/thing" instead of "/some/thing". Maybe the relative_to method should default to a |
Yeah, you're right, there's no access to the filesystem and the result I've looked into the test suite, it helped a lot especially with Any input is appreciated. |
Thank you for your work on this Domenico. For reviewing the code, would you mind creating a Github pull request for it as described here https://devguide.python.org/pullrequest/ |
I may have forgotten to use the proper format for the title of each On Thu, Apr 30, 2020 at 2:03 AM Roundup Robot <report@bugs.python.org> wrote:
|
On bpo-44078 (closed as duplicate), Mark Hammond made a similar request. |
Also requested in bpo-42234. |
For the record, requested on Discourse as well, with a fairly similar proposal. |
If both arguments to def relative_to(self, *other):
if not other:
raise TypeError("need at least one argument")
other = type(self)(*other)
if self.is_absolute() != other.is_absolute():
raise ValueError("one path is relative and the other is absolute: "
"{!r}, {!r}".format(str(self), str(other)))
rel = self._flavour.relpath(self, other)
return type(self)(rel) |
An interesting comment in # For the purpose of this method, drive and root are considered
# separate parts, i.e.:
# Path('c:/').relative_to('c:') gives Path('/')
# Path('c:/').relative_to('/') raise ValueError This isn't true for >>> import ntpath
>>> ntpath.relpath('c:\\', 'c:')
'.' Pathlib's behaviour is deliberate but questionable. If we're willing to drop it, then we can call through to Also, |
"C:" is the current directory in drive C, so I think pathlib's answer is the correct one here (of course, I wrote it so I may be biaised :-)). |
Thanks Antoine! That makes sense, but it still seems a odd to me that naked Windows drive paths are the only place where absolute and relative paths can be mixed! Extending your logic:
Both of these raise |
I would say it is a practically beats purity thing indeed. I don't remember the details of why I chose to allow it at the time. |
Correction to my earlier post:
>>> import ntpath
>>> ntpath.relpath('C:\\', start='C:')
'..\\..'
>>> ntpath.relpath('C:\\', start='C:foo')
'..\\..\\..' Here's >>> import pathlib
>>> pathlib.PureWindowsPath('C:/').relative_to('C:')
PureWindowsPath('/')
>>> pathlib.PureWindowsPath('C:/').relative_to('C:foo')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/barney.gale/code/cpython/Lib/pathlib.py", line 673, in relative_to
raise ValueError("{!r} is not in the subpath of {!r}"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: 'C:\\' is not in the subpath of 'C:foo' OR one path is relative and the other is absolute. |
By default, :meth:`pathlib.PurePath.relative_to` doesn't deal with paths that are not a direct prefix of the other, raising an exception in that instance. This change adds a *walk_up* parameter that can be set to allow for using ``..`` to calculate the relative path. example: ``` >>> p = PurePosixPath('/etc/passwd') >>> p.relative_to('/etc') PurePosixPath('passwd') >>> p.relative_to('/usr') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "pathlib.py", line 940, in relative_to raise ValueError(error_message.format(str(self), str(formatted))) ValueError: '/etc/passwd' does not start with '/usr' >>> p.relative_to('/usr', strict=False) PurePosixPath('../etc/passwd') ``` https://bugs.python.org/issue40358 Automerge-Triggered-By: GH:brettcannon
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: