14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"""Common operations on Posix pathnames.
24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmInstead of importing this module directly, import os and refer to
44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmthis module as os.path.  The "os.path" name is an alias for this
54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmodule on Posix systems; on other systems (e.g. Mac, Windows),
64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmos.path provides the same operations in a manner specific to that
74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmplatform, and is an alias to another module (e.g. macpath, ntpath).
84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSome of this can actually be useful on non-Posix systems too, e.g.
104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfor manipulation of the pathname component of URLs.
114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"""
124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport os
144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport sys
154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport stat
164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport genericpath
174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport warnings
184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom genericpath import *
194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm           "basename","dirname","commonprefix","getsize","getmtime",
224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm           "getatime","getctime","islink","exists","lexists","isdir","isfile",
234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm           "ismount","walk","expanduser","expandvars","normpath","abspath",
244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm           "samefile","sameopenfile","samestat",
254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm           "curdir","pardir","sep","pathsep","defpath","altsep","extsep",
264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm           "devnull","realpath","supports_unicode_filenames","relpath"]
274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# strings representing various path-related bits and pieces
294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmcurdir = '.'
304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpardir = '..'
314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmextsep = '.'
324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmsep = '/'
334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpathsep = ':'
344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdefpath = ':/bin:/usr/bin'
354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmaltsep = None
364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdevnull = '/dev/null'
374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Normalize the case of a pathname.  Trivial in Posix, string.lower on Mac.
394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# On MS-DOS this may also turn slashes into backslashes; however, other
404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# normalizations (such as optimizing '../' away) are not allowed
414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# (another function should be defined to do that).
424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef normcase(s):
444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Normalize case of pathname.  Has no effect under Posix"""
454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return s
464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Return whether a path is absolute.
494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Trivial in Posix, harder on the Mac or MS-DOS.
504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef isabs(s):
524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Test whether a path is absolute"""
534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return s.startswith('/')
544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Join pathnames.
574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Ignore the previous parts if a part is absolute.
584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Insert a '/' unless the first part is empty or already ends in '/'.
594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef join(a, *p):
614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Join two or more pathname components, inserting '/' as needed.
624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    If any component is an absolute path, all previous path components
634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    will be discarded."""
644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    path = a
654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    for b in p:
664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if b.startswith('/'):
674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            path = b
684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        elif path == '' or path.endswith('/'):
694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            path +=  b
704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            path += '/' + b
724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return path
734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Split a path in head (everything up to the last '/') and tail (the
764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# rest).  If the path ends in '/', tail will be empty.  If there is no
774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# '/' in the path, head  will be empty.
784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Trailing '/'es are stripped from head unless it is the root.
794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef split(p):
814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Split a pathname.  Returns tuple "(head, tail)" where "tail" is
824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    everything after the final slash.  Either part may be empty."""
834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    i = p.rfind('/') + 1
844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    head, tail = p[:i], p[i:]
854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if head and head != '/'*len(head):
864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        head = head.rstrip('/')
874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return head, tail
884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Split a path in root and extension.
914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# The extension is everything starting at the last dot in the last
924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# pathname component; the root is everything before that.
934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# It is always true that root + ext == p.
944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef splitext(p):
964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return genericpath._splitext(p, sep, altsep, extsep)
974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmsplitext.__doc__ = genericpath._splitext.__doc__
984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Split a pathname into a drive specification and the rest of the
1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# path.  Useful on DOS/Windows/NT; on Unix, the drive is always empty.
1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef splitdrive(p):
1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Split a pathname into drive and path. On Posix, drive is always
1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    empty."""
1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return '', p
1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Return the tail (basename) part of a path, same as split(path)[1].
1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef basename(p):
1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Returns the final component of a pathname"""
1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    i = p.rfind('/') + 1
1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return p[i:]
1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Return the head (dirname) part of a path, same as split(path)[0].
1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef dirname(p):
1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Returns the directory component of a pathname"""
1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    i = p.rfind('/') + 1
1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    head = p[:i]
1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if head and head != '/'*len(head):
1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        head = head.rstrip('/')
1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return head
1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Is a path a symbolic link?
1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# This will always return false on systems where os.lstat doesn't exist.
1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef islink(path):
1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Test whether a path is a symbolic link"""
1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    try:
1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        st = os.lstat(path)
1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    except (os.error, AttributeError):
1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return False
1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return stat.S_ISLNK(st.st_mode)
1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Being true for dangling symbolic links is also useful.
1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef lexists(path):
1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Test whether a path exists.  Returns True for broken symbolic links"""
1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    try:
1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        os.lstat(path)
1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    except os.error:
1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return False
1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return True
1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Are two filenames really pointing to the same file?
1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef samefile(f1, f2):
1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Test whether two pathnames reference the same actual file"""
1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    s1 = os.stat(f1)
1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    s2 = os.stat(f2)
1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return samestat(s1, s2)
1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Are two open files really referencing the same file?
1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# (Not necessarily the same file descriptor!)
1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef sameopenfile(fp1, fp2):
1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Test whether two open file objects reference the same file"""
1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    s1 = os.fstat(fp1)
1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    s2 = os.fstat(fp2)
1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return samestat(s1, s2)
1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Are two stat buffers (obtained from stat, fstat or lstat)
1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# describing the same file?
1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef samestat(s1, s2):
1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Test whether two stat buffers reference the same file"""
1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return s1.st_ino == s2.st_ino and \
1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm           s1.st_dev == s2.st_dev
1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Is a path a mount point?
1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# (Does this work for all UNIXes?  Is it even guaranteed to work by Posix?)
1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef ismount(path):
1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Test whether a path is a mount point"""
1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if islink(path):
1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # A symlink can never be a mount point
1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return False
1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    try:
1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        s1 = os.lstat(path)
1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        s2 = os.lstat(join(path, '..'))
1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    except os.error:
1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return False # It doesn't exist -- so not a mount point :-)
1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    dev1 = s1.st_dev
1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    dev2 = s2.st_dev
1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if dev1 != dev2:
1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return True     # path/.. on a different device as path
1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ino1 = s1.st_ino
1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    ino2 = s2.st_ino
1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if ino1 == ino2:
1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return True     # path/.. is the same i-node as path
1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return False
1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Directory tree walk.
2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# For each directory under top (including top itself, but excluding
2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# '.' and '..'), func(arg, dirname, filenames) is called, where
2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# dirname is the name of the directory and filenames is the list
2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# of files (and subdirectories etc.) in the directory.
2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# The func may modify the filenames list, to implement a filter,
2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# or to impose a different order of visiting.
2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef walk(top, func, arg):
2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Directory tree walk with callback function.
2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    For each directory in the directory tree rooted at top (including top
2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    dirname is the name of the directory, and fnames a list of the names of
2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    the files and subdirectories in dirname (excluding '.' and '..').  func
2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    may modify the fnames list in-place (e.g. via del or slice assignment),
2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    and walk will only recurse into the subdirectories whose names remain in
2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    fnames; this can be used to implement a filter, or to impose a specific
2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    order of visiting.  No semantics are defined for, or required of, arg,
2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    beyond that arg is always passed to func.  It can be used, e.g., to pass
2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    a filename pattern, or a mutable object designed to accumulate
2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    statistics.  Passing None for arg is common."""
2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    warnings.warnpy3k("In 3.x, os.path.walk is removed in favor of os.walk.",
2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                      stacklevel=2)
2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    try:
2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        names = os.listdir(top)
2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    except os.error:
2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return
2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    func(arg, top, names)
2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    for name in names:
2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        name = join(top, name)
2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            st = os.lstat(name)
2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except os.error:
2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            continue
2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if stat.S_ISDIR(st.st_mode):
2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            walk(name, func, arg)
2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Expand paths beginning with '~' or '~user'.
2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# '~' means $HOME; '~user' means that user's home directory.
2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# If the path doesn't begin with '~', or if the user or $HOME is unknown,
2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# the path is returned unchanged (leaving error reporting to whatever
2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# function is called with the expanded path as argument).
2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# See also module 'glob' for expansion of *, ? and [...] in pathnames.
2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# (A function should also be defined to do full *sh-style environment
2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# variable expansion.)
2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef expanduser(path):
2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Expand ~ and ~user constructions.  If user or $HOME is unknown,
2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    do nothing."""
2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if not path.startswith('~'):
2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return path
2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    i = path.find('/', 1)
2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if i < 0:
2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        i = len(path)
2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if i == 1:
2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if 'HOME' not in os.environ:
2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            import pwd
2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            userhome = pwd.getpwuid(os.getuid()).pw_dir
2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            userhome = os.environ['HOME']
2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else:
2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        import pwd
2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            pwent = pwd.getpwnam(path[1:i])
2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except KeyError:
2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return path
2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        userhome = pwent.pw_dir
2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    userhome = userhome.rstrip('/') or userhome
2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return userhome + path[i:]
2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Expand paths containing shell variable substitutions.
2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# This expands the forms $variable and ${variable} only.
2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Non-existent variables are left unchanged.
2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm_varprog = None
2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef expandvars(path):
2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Expand shell variables of form $var and ${var}.  Unknown variables
2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    are left unchanged."""
2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    global _varprog
2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if '$' not in path:
2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return path
2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if not _varprog:
2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        import re
2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        _varprog = re.compile(r'\$(\w+|\{[^}]*\})')
2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    i = 0
2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    while True:
2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m = _varprog.search(path, i)
2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if not m:
2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            break
2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        i, j = m.span(0)
2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        name = m.group(1)
2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if name.startswith('{') and name.endswith('}'):
2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            name = name[1:-1]
2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if name in os.environ:
2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            tail = path[j:]
3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            path = path[:i] + os.environ[name]
3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            i = len(path)
3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            path += tail
3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            i = j
3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return path
3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# It should be understood that this may change the meaning of the path
3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# if it contains symbolic links!
3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef normpath(path):
3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Normalize path, eliminating double slashes, etc."""
3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # Preserve unicode (if path is unicode)
3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    slash, dot = (u'/', u'.') if isinstance(path, unicode) else ('/', '.')
3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if path == '':
3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return dot
3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    initial_slashes = path.startswith('/')
3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # POSIX allows one or two initial slashes, but treats three or more
3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # as single slash.
3214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if (initial_slashes and
3224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        path.startswith('//') and not path.startswith('///')):
3234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        initial_slashes = 2
3244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    comps = path.split('/')
3254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    new_comps = []
3264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    for comp in comps:
3274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if comp in ('', '.'):
3284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            continue
3294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (comp != '..' or (not initial_slashes and not new_comps) or
3304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm             (new_comps and new_comps[-1] == '..')):
3314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            new_comps.append(comp)
3324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        elif new_comps:
3334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            new_comps.pop()
3344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    comps = new_comps
3354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    path = slash.join(comps)
3364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if initial_slashes:
3374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        path = slash*initial_slashes + path
3384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return path or dot
3394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef abspath(path):
3424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Return an absolute path."""
3434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if not isabs(path):
3444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isinstance(path, unicode):
3454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cwd = os.getcwdu()
3464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
3474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cwd = os.getcwd()
3484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        path = join(cwd, path)
3494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return normpath(path)
3504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Return a canonical path (i.e. the absolute location of a file on the
3534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# filesystem).
3544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef realpath(filename):
3564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Return the canonical path of the specified filename, eliminating any
3574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmsymbolic links encountered in the path."""
3584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if isabs(filename):
3594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        bits = ['/'] + filename.split('/')[1:]
3604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    else:
3614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        bits = [''] + filename.split('/')
3624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    for i in range(2, len(bits)+1):
3644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        component = join(*bits[0:i])
3654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Resolve symbolic links.
3664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if islink(component):
3674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            resolved = _resolve_link(component)
3684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if resolved is None:
3694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # Infinite loop -- return original component + rest of the path
3704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return abspath(join(*([component] + bits[i:])))
3714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else:
3724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                newpath = join(*([resolved] + bits[i:]))
3734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return realpath(newpath)
3744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return abspath(filename)
3764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef _resolve_link(path):
3794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Internal helper function.  Takes a path and follows symlinks
3804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    until we either arrive at something that isn't a symlink, or
3814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    encounter a path we've seen before (meaning that there's a loop).
3824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
3834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    paths_seen = set()
3844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    while islink(path):
3854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if path in paths_seen:
3864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Already seen this path, so we must have a symlink loop
3874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return None
3884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        paths_seen.add(path)
3894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Resolve where the link points to
3904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        resolved = os.readlink(path)
3914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if not isabs(resolved):
3924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            dir = dirname(path)
3934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            path = normpath(join(dir, resolved))
3944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
3954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            path = normpath(resolved)
3964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return path
3974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmsupports_unicode_filenames = (sys.platform == 'darwin')
3994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef relpath(path, start=curdir):
4014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Return a relative version of a path"""
4024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if not path:
4044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        raise ValueError("no path specified")
4054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    start_list = [x for x in abspath(start).split(sep) if x]
4074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    path_list = [x for x in abspath(path).split(sep) if x]
4084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # Work out how much of the filepath is shared by start and path.
4104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    i = len(commonprefix([start_list, path_list]))
4114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
4134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if not rel_list:
4144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return curdir
4154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return join(*rel_list)
416