GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Disagreement between `PureWindowsPath.relative_to()` and `ntpath.relpath()` with rootless drives · Issue #99029 · python/cpython

Disagreement between PureWindowsPath.relative_to() and ntpath.relpath() with rootless drives #99029

New issue
Copy link
New issue
Copy link
Closed
Closed
Disagreement between PureWindowsPath.relative_to() and ntpath.relpath() with rootless drives#99029
Copy link
Labels
OS-windowstopic-pathlibtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

@barneygale
barneygale
opened on Nov 2, 2022
Issue body actions

On Windows, the path C: means "the current directory on the C: drive".

But pathlib's relative_to() treats it as the immediate parent of C:\. This makes sense lexographically, but it's inconsistent with everything else:

C:\Users\Barney>python
>>> import ntpath, pathlib
>>> ntpath.relpath('C:/Windows', 'C:/Users/Barney')
'..\\..\\Windows'
>>> ntpath.relpath('C:/Windows', '.')
'..\\..\\Windows'
>>> ntpath.relpath('C:/Windows', 'C:')
'..\\..\\Windows'
>>> pathlib.Path('C:/Windows').relative_to('C:/Users/Barney', walk_up=True)
WindowsPath('../../Windows')
>>> pathlib.Path('C:/Windows').relative_to('.', walk_up=True)
ValueError: One path is relative and the other is absolute.
>>> pathlib.Path('C:/Windows').relative_to('C:')
WindowsPath('/Windows')  # should be ValueError, as we're mixing absolute + relative paths

This prevents us from using relpath() from pathlib, and renders the two implementations incompatible. Booo! Also prevents us from simplifying is_relative_to() down to other == self or other in self.parents

Special cases aren't special enough to break the rules. Let's make these compatible!

Previous discussion: #84538

  • PR: gh-99029: Fix handling of PureWindowsPath('C:\<blah>').relative_to('C:') #99031

Activity

  1. barneygale
    added
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on Nov 2, 2022
  2. barneygale
    added a commit that references this issue on Nov 2, 2022

    pythongh-99029: Fix handling of `PureWindowsPath('C:\<blah>').relativ…

    bdfcc65
  3. mdboom
    added
    OS-windows
    topic-pathlib
    on Nov 3, 2022
  4. brettcannon commented on Nov 4, 2022

    @brettcannon
    brettcannon
    on Nov 4, 2022
    Member
    More actions

    @zooba @eryksun any reason to not standardize on os.path.relpath() instead of pathlib's custom code?

  5. zooba commented on Nov 7, 2022

    @zooba
    zooba
    on Nov 7, 2022
    Member
    More actions

    Pathlib uses a pure implementation that doesn't rely on global state, such as the current working directory or current operating system (the implementation is in PurePath.relative_to). We don't resolve symlinks or junctions here, so why would we combine it with CWD?

    If anything, we should make relative_to raise because C: is a relative path, and it requires an absolute path. There's a note saying that it treats a pathless root like this on purpose, but it's in a comment and not the docstring.

    Provided walk_up=True doesn't affect this result, the result is correct. Anywhere on the C drive combined with \Windows will get to the right path - if it gets ..\..\Windows then it's incorrect. But I didn't try this because it's new in 3.12 and so we can change the behaviour if we feel like it.

  6. barneygale commented on Nov 7, 2022

    @barneygale
    barneygale
    on Nov 7, 2022
    ContributorAuthor
    More actions

    If anything, we should make relative_to raise because C: is a relative path, and it requires an absolute path. There's a note saying that it treats a pathless root like this on purpose, but it's in a comment and not the docstring.

    Indeed. This seems to be the only case where a.relative_path(b) allows a and b to have different anchors (e.g. one relative, one absolute; or different Windows drives); in all other cases, ValueError is raised. My suggestion here is that we make Path('C:/Windows').relative_to('C:') also raise.

    I've logged #99199 to cover relpath() calling abspath(). It doesn't cause us any problems for us in pathlib, though (see discussion on #99031). It's "wrong" but has no observable effect, as far as I can tell.

    Reacted by Steve Dower
  7. barneygale commented on Nov 12, 2022

    @barneygale
    barneygale
    on Nov 12, 2022
    ContributorAuthor
    More actions

    I found another incompatibility between PurePath.relative_to() and os.path.relpath() - see #99199 (comment)

    This bug is still valid, but we can't fix it by using relpath(). I've revised my PR.

  8. brettcannon
    added a commit that references this issue on Nov 25, 2022

    gh-99029: Fix handling of `PureWindowsPath('C:\<blah>').relative_to('…

    ae234fb
  9. brettcannon
    closed this as completedon Nov 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    OS-windowstopic-pathlibtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.