How to do relpath implementation on 2.5

Brian Allen Vanderburg II BrianVanderburg2 at
Sun Aug 9 03:08:38 CEST 2009

I've coded my own 'relpath' implementation for 2.5 (shown below) and I 
want to make sure it follows as closely as it should to 2.6 and later.  
I've got a question regarding that.  When attempting to convert to a 
relative path and it is not possible for some reason (different drive or 
UNC share), should that be an error or should it return the absolute 
path of the target?  I'm using Debian so I don't have 2.6 available 
right now for testing.

This is what I've got so far

import os
from os import path

def relpath(target, origin=os.curdir):
    Determine relative path of target to origin or

    target = path.normcase(path.abspath(path.normpath(target)))
    origin = path.normcase(path.abspath(path.normpath(origin)))

    # Same?
    if target == origin:
        return '.'

    original_target = target

    # Check drive (for Windows)
    (tdrive, target) = path.splitdrive(target)
    (odrive, origin) = path.splitdrive(origin)
    if tdrive != odrive:
        return original_target

    # Check UNC path (for Windows)
    # If they are on different shares, we want an absolute path
    if not tdrive and not odrive and hasattr(path, 'splitunc'):
        (tunc, target) = path.splitunc(target)
        (ounc, origin) = path.splitunc(origin)
        if tunc != ounc:
            return original_target

    # Split into lists
    target_list = target.split(os.sep)
    origin_list = origin.split(os.sep)

    # Remove beginning empty parts
    # Helps to handle when one item may be in the root
    while target_list and not target_list[0]:
        del target_list[0]
    while origin_list and not origin_list[0]:
        del origin_list[0]

    # Remove common items
    while origin_list and target_list:
        if origin_list[0] == target_list[0]:
            del origin_list[0]
            del target_list[0]

    # Combine and return the result
    relative_list = [os.pardir] * len(origin_list) + target_list
    if not relative_list:
        return os.curdir
    return os.sep.join(relative_list)

Currently I just return the target if it can not be made relative.

Brian A. Vanderburg II

More information about the Python-list mailing list