1import os 2import sys 3 4try: 5 from functools import wraps 6except ImportError: 7 # only needed for Python 2.4 8 def wraps(_): 9 def _wraps(func): 10 return func 11 return _wraps 12 13__unittest = True 14 15 16def _relpath_nt(path, start=os.path.curdir): 17 """Return a relative version of a path""" 18 19 if not path: 20 raise ValueError("no path specified") 21 start_list = os.path.abspath(start).split(os.path.sep) 22 path_list = os.path.abspath(path).split(os.path.sep) 23 if start_list[0].lower() != path_list[0].lower(): 24 unc_path, rest = os.path.splitunc(path) 25 unc_start, rest = os.path.splitunc(start) 26 if bool(unc_path) ^ bool(unc_start): 27 raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)" 28 % (path, start)) 29 else: 30 raise ValueError("path is on drive %s, start on drive %s" 31 % (path_list[0], start_list[0])) 32 # Work out how much of the filepath is shared by start and path. 33 for i in range(min(len(start_list), len(path_list))): 34 if start_list[i].lower() != path_list[i].lower(): 35 break 36 else: 37 i += 1 38 39 rel_list = [os.path.pardir] * (len(start_list) - i) + path_list[i:] 40 if not rel_list: 41 return os.path.curdir 42 return os.path.join(*rel_list) 43 44# default to posixpath definition 45 46 47def _relpath_posix(path, start=os.path.curdir): 48 """Return a relative version of a path""" 49 50 if not path: 51 raise ValueError("no path specified") 52 53 start_list = os.path.abspath(start).split(os.path.sep) 54 path_list = os.path.abspath(path).split(os.path.sep) 55 56 # Work out how much of the filepath is shared by start and path. 57 i = len(os.path.commonprefix([start_list, path_list])) 58 59 rel_list = [os.path.pardir] * (len(start_list) - i) + path_list[i:] 60 if not rel_list: 61 return os.path.curdir 62 return os.path.join(*rel_list) 63 64if os.path is sys.modules.get('ntpath'): 65 relpath = _relpath_nt 66else: 67 relpath = _relpath_posix 68