Home | History | Annotate | Download | only in python2.7
      1 """Pathname and path-related operations for the Macintosh."""
      2 
      3 import os
      4 import warnings
      5 from stat import *
      6 import genericpath
      7 from genericpath import *
      8 
      9 __all__ = ["normcase","isabs","join","splitdrive","split","splitext",
     10            "basename","dirname","commonprefix","getsize","getmtime",
     11            "getatime","getctime", "islink","exists","lexists","isdir","isfile",
     12            "walk","expanduser","expandvars","normpath","abspath",
     13            "curdir","pardir","sep","pathsep","defpath","altsep","extsep",
     14            "devnull","realpath","supports_unicode_filenames"]
     15 
     16 # strings representing various path-related bits and pieces
     17 curdir = ':'
     18 pardir = '::'
     19 extsep = '.'
     20 sep = ':'
     21 pathsep = '\n'
     22 defpath = ':'
     23 altsep = None
     24 devnull = 'Dev:Null'
     25 
     26 # Normalize the case of a pathname.  Dummy in Posix, but <s>.lower() here.
     27 
     28 def normcase(path):
     29     return path.lower()
     30 
     31 
     32 def isabs(s):
     33     """Return true if a path is absolute.
     34     On the Mac, relative paths begin with a colon,
     35     but as a special case, paths with no colons at all are also relative.
     36     Anything else is absolute (the string up to the first colon is the
     37     volume name)."""
     38 
     39     return ':' in s and s[0] != ':'
     40 
     41 
     42 def join(s, *p):
     43     path = s
     44     for t in p:
     45         if (not s) or isabs(t):
     46             path = t
     47             continue
     48         if t[:1] == ':':
     49             t = t[1:]
     50         if ':' not in path:
     51             path = ':' + path
     52         if path[-1:] != ':':
     53             path = path + ':'
     54         path = path + t
     55     return path
     56 
     57 
     58 def split(s):
     59     """Split a pathname into two parts: the directory leading up to the final
     60     bit, and the basename (the filename, without colons, in that directory).
     61     The result (s, t) is such that join(s, t) yields the original argument."""
     62 
     63     if ':' not in s: return '', s
     64     colon = 0
     65     for i in range(len(s)):
     66         if s[i] == ':': colon = i + 1
     67     path, file = s[:colon-1], s[colon:]
     68     if path and not ':' in path:
     69         path = path + ':'
     70     return path, file
     71 
     72 
     73 def splitext(p):
     74     return genericpath._splitext(p, sep, altsep, extsep)
     75 splitext.__doc__ = genericpath._splitext.__doc__
     76 
     77 def splitdrive(p):
     78     """Split a pathname into a drive specification and the rest of the
     79     path.  Useful on DOS/Windows/NT; on the Mac, the drive is always
     80     empty (don't use the volume name -- it doesn't have the same
     81     syntactic and semantic oddities as DOS drive letters, such as there
     82     being a separate current directory per drive)."""
     83 
     84     return '', p
     85 
     86 
     87 # Short interfaces to split()
     88 
     89 def dirname(s): return split(s)[0]
     90 def basename(s): return split(s)[1]
     91 
     92 def ismount(s):
     93     if not isabs(s):
     94         return False
     95     components = split(s)
     96     return len(components) == 2 and components[1] == ''
     97 
     98 def islink(s):
     99     """Return true if the pathname refers to a symbolic link."""
    100 
    101     try:
    102         import Carbon.File
    103         return Carbon.File.ResolveAliasFile(s, 0)[2]
    104     except:
    105         return False
    106 
    107 # Is `stat`/`lstat` a meaningful difference on the Mac?  This is safe in any
    108 # case.
    109 
    110 def lexists(path):
    111     """Test whether a path exists.  Returns True for broken symbolic links"""
    112 
    113     try:
    114         st = os.lstat(path)
    115     except os.error:
    116         return False
    117     return True
    118 
    119 def expandvars(path):
    120     """Dummy to retain interface-compatibility with other operating systems."""
    121     return path
    122 
    123 
    124 def expanduser(path):
    125     """Dummy to retain interface-compatibility with other operating systems."""
    126     return path
    127 
    128 class norm_error(Exception):
    129     """Path cannot be normalized"""
    130 
    131 def normpath(s):
    132     """Normalize a pathname.  Will return the same result for
    133     equivalent paths."""
    134 
    135     if ":" not in s:
    136         return ":"+s
    137 
    138     comps = s.split(":")
    139     i = 1
    140     while i < len(comps)-1:
    141         if comps[i] == "" and comps[i-1] != "":
    142             if i > 1:
    143                 del comps[i-1:i+1]
    144                 i = i - 1
    145             else:
    146                 # best way to handle this is to raise an exception
    147                 raise norm_error, 'Cannot use :: immediately after volume name'
    148         else:
    149             i = i + 1
    150 
    151     s = ":".join(comps)
    152 
    153     # remove trailing ":" except for ":" and "Volume:"
    154     if s[-1] == ":" and len(comps) > 2 and s != ":"*len(s):
    155         s = s[:-1]
    156     return s
    157 
    158 
    159 def walk(top, func, arg):
    160     """Directory tree walk with callback function.
    161 
    162     For each directory in the directory tree rooted at top (including top
    163     itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
    164     dirname is the name of the directory, and fnames a list of the names of
    165     the files and subdirectories in dirname (excluding '.' and '..').  func
    166     may modify the fnames list in-place (e.g. via del or slice assignment),
    167     and walk will only recurse into the subdirectories whose names remain in
    168     fnames; this can be used to implement a filter, or to impose a specific
    169     order of visiting.  No semantics are defined for, or required of, arg,
    170     beyond that arg is always passed to func.  It can be used, e.g., to pass
    171     a filename pattern, or a mutable object designed to accumulate
    172     statistics.  Passing None for arg is common."""
    173     warnings.warnpy3k("In 3.x, os.path.walk is removed in favor of os.walk.",
    174                       stacklevel=2)
    175     try:
    176         names = os.listdir(top)
    177     except os.error:
    178         return
    179     func(arg, top, names)
    180     for name in names:
    181         name = join(top, name)
    182         if isdir(name) and not islink(name):
    183             walk(name, func, arg)
    184 
    185 
    186 def abspath(path):
    187     """Return an absolute path."""
    188     if not isabs(path):
    189         if isinstance(path, unicode):
    190             cwd = os.getcwdu()
    191         else:
    192             cwd = os.getcwd()
    193         path = join(cwd, path)
    194     return normpath(path)
    195 
    196 # realpath is a no-op on systems without islink support
    197 def realpath(path):
    198     path = abspath(path)
    199     try:
    200         import Carbon.File
    201     except ImportError:
    202         return path
    203     if not path:
    204         return path
    205     components = path.split(':')
    206     path = components[0] + ':'
    207     for c in components[1:]:
    208         path = join(path, c)
    209         try:
    210             path = Carbon.File.FSResolveAliasFile(path, 1)[0].as_pathname()
    211         except Carbon.File.Error:
    212             pass
    213     return path
    214 
    215 supports_unicode_filenames = True
    216