• Does os.path relpath produce an incorrect relative path?

    From BlindAnagram@21:1/5 to All on Thu May 25 08:49:06 2023
    I am wondering whether I have misunderstood the semantics of os.path
    relpath or whether it has a bug.

    Here is a short test program:

    -----------------------------------------------------------
    from os.path import relpath, split

    src_path = 'C:\\lib\\src\\'

    vcx_path = 'C:\\build.vs22\\lib\\lib.vcxproj'
    rel_path = relpath(src_path, vcx_path)
    print(f"{vcx_path = }\n{src_path = }\n{rel_path = }\n")

    vcx_path = 'C:\\build.vs22\\lib\\'
    rel_path = relpath(src_path, vcx_path)
    print(f"{vcx_path = }\n{src_path = }\n{rel_path = }\n")

    vcx_path = 'C:\\build.vs22\\lib\\lib.vcxproj'
    rel_path = relpath(src_path, split(vcx_path)[0])
    print(f"{vcx_path = }\n{src_path = }\n{rel_path = }\n") -----------------------------------------------------------

    and its output with Python 3.11:

    -----------------------------------------------------------
    vcx_path = 'C:\\build.vs22\\lib\\lib.vcxproj'
    src_path = 'C:\\lib\\src\\'
    rel_path = '..\\..\\..\\lib\\src'

    vcx_path = 'C:\\build.vs22\\lib\\'
    src_path = 'C:\\lib\\src\\'
    rel_path = '..\\..\\lib\\src'

    vcx_path = 'C:\\build.vs22\\lib\\lib.vcxproj'
    src_path = 'C:\\lib\\src\\'
    rel_path = '..\\..\\lib\\src' -----------------------------------------------------------

    The first of these three results produces an incorrect relative path
    because relpath does not strip off any non-directory tails before
    comparing paths.

    Is this a bug or my misunderstanding of relpath semantics?

    Comments would be appreciated as I don't waste developer time if this is
    not a bug.

    regards

    Brian

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Eryk Sun@21:1/5 to BlindAnagram on Thu May 25 10:53:13 2023
    On 5/25/23, BlindAnagram <BlindAnagram@nowhere.org> wrote:

    vcx_path = 'C:\\build.vs22\\lib\\lib.vcxproj'
    src_path = 'C:\\lib\\src\\'
    rel_path = '..\\..\\..\\lib\\src'

    [snip]

    The first of these three results produces an incorrect relative path
    because relpath does not strip off any non-directory tails before
    comparing paths.

    The start path is assumed to be a directory, which defaults to the
    current working directory, and the input paths are first resolved as
    absolute paths. In order to reach src_path from vcx_path, one has to
    traverse 3 levels up to the root directory.

    https://docs.python.org/3/library/os.path.html#os.path.relpath

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Ewing@21:1/5 to BlindAnagram on Fri May 26 04:02:45 2023
    On 25/05/23 7:49 pm, BlindAnagram wrote:
    The first of these three results produces an incorrect relative path
    because relpath does not strip off any non-directory tails before
    comparing paths.

    It has no way of knowing whether a pathname component is a directory
    or not. It's purely an operation on strings, it doesn't look in the
    file system.

    --
    Greg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From MRAB@21:1/5 to Eryk Sun on Thu May 25 17:52:01 2023
    On 2023-05-25 16:53, Eryk Sun wrote:
    On 5/25/23, BlindAnagram <BlindAnagram@nowhere.org> wrote:

    vcx_path = 'C:\\build.vs22\\lib\\lib.vcxproj'
    src_path = 'C:\\lib\\src\\'
    rel_path = '..\\..\\..\\lib\\src'

    [snip]

    The first of these three results produces an incorrect relative path
    because relpath does not strip off any non-directory tails before
    comparing paths.

    The start path is assumed to be a directory, which defaults to the
    current working directory, and the input paths are first resolved as
    absolute paths. In order to reach src_path from vcx_path, one has to
    traverse 3 levels up to the root directory.

    https://docs.python.org/3/library/os.path.html#os.path.relpath

    Well, it's not necessarily the optimal relative path, because it's not
    always necessary to go all the way up to the root, as in the first example.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From cactus@21:1/5 to MRAB on Fri May 26 05:41:14 2023
    On Thursday, 25 May 2023 at 17:57:21 UTC+1, MRAB wrote:
    On 2023-05-25 16:53, Eryk Sun wrote:
    On 5/25/23, BlindAnagram <BlindA...@nowhere.org> wrote:

    vcx_path = 'C:\\build.vs22\\lib\\lib.vcxproj'
    src_path = 'C:\\lib\\src\\'
    rel_path = '..\\..\\..\\lib\\src'

    [snip]

    The first of these three results produces an incorrect relative path
    because relpath does not strip off any non-directory tails before
    comparing paths.

    The start path is assumed to be a directory, which defaults to the
    current working directory, and the input paths are first resolved as absolute paths. In order to reach src_path from vcx_path, one has to traverse 3 levels up to the root directory.

    https://docs.python.org/3/library/os.path.html#os.path.relpath
    Well, it's not necessarily the optimal relative path, because it's not always necessary to go all the way up to the root, as in the first example.

    Thanks to all for their comments.

    I was hoping that there would be an direct way in Python to find a relative path between two paths in which the convention is that all directories end with '\\' so that it is possible to distinguish the 'tail' references to files as not part of the path
    comparison.

    But I will just have to remember to strip the file tails myself.

    Surprisingly (for me at least) the alternative provided by the pathlib module 'relative_to' method doesn't provide for full relative path computation. I was expecting this would offer everything that os.path offers but it doesn't in this case.

    Brian

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Eryk Sun@21:1/5 to cactus on Fri May 26 10:42:01 2023
    On 5/26/23, cactus <riemannic@gmail.com> wrote:

    Surprisingly (for me at least) the alternative provided by the pathlib
    module 'relative_to' method doesn't provide for full relative path computation. I was expecting this would offer everything that os.path
    offers but it doesn't in this case.

    Starting with Python 3.12, the relative_to() method has a walk_up
    parameter. It defaults to False for the sake of backward
    compatibility.

    https://docs.python.org/3.12/library/pathlib.html#pathlib.PurePath.relative_to

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From BlindAnagram@21:1/5 to Eryk Sun on Sat May 27 10:21:34 2023
    On 26/05/2023 16:42, Eryk Sun wrote:
    On 5/26/23, cactus <riemannic@gmail.com> wrote:

    Surprisingly (for me at least) the alternative provided by the pathlib
    module 'relative_to' method doesn't provide for full relative path
    computation. I was expecting this would offer everything that os.path
    offers but it doesn't in this case.

    Starting with Python 3.12, the relative_to() method has a walk_up
    parameter. It defaults to False for the sake of backward
    compatibility.

    https://docs.python.org/3.12/library/pathlib.html#pathlib.PurePath.relative_to

    Thanks, it is good to know that this is coming.

    Brian

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)