macpath.py 5.31 KB
Newer Older
1
"""Pathname and path-related operations for the Macintosh."""
Guido van Rossum's avatar
Guido van Rossum committed
2

3
import os
Guido van Rossum's avatar
Guido van Rossum committed
4
from stat import *
5
import genericpath
6
from genericpath import *
Guido van Rossum's avatar
Guido van Rossum committed
7

8 9
__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
           "basename","dirname","commonprefix","getsize","getmtime",
10
           "getatime","getctime", "islink","exists","lexists","isdir","isfile",
Benjamin Peterson's avatar
Benjamin Peterson committed
11
           "expanduser","expandvars","normpath","abspath",
12
           "curdir","pardir","sep","pathsep","defpath","altsep","extsep",
13
           "devnull","realpath","supports_unicode_filenames"]
14

15
# strings representing various path-related bits and pieces
16
# These are primarily for export; internally, they are hardcoded.
17 18 19 20 21 22 23
curdir = ':'
pardir = '::'
extsep = '.'
sep = ':'
pathsep = '\n'
defpath = ':'
altsep = None
24
devnull = 'Dev:Null'
25

26 27 28 29 30 31
def _get_colon(path):
    if isinstance(path, bytes):
        return b':'
    else:
        return ':'

32
# Normalize the case of a pathname.  Dummy in Posix, but <s>.lower() here.
33

34 35
def normcase(path):
    return path.lower()
36 37


Guido van Rossum's avatar
Guido van Rossum committed
38
def isabs(s):
39 40 41 42 43 44
    """Return true if a path is absolute.
    On the Mac, relative paths begin with a colon,
    but as a special case, paths with no colons at all are also relative.
    Anything else is absolute (the string up to the first colon is the
    volume name)."""

45 46
    colon = _get_colon(s)
    return colon in s and s[:1] != colon
Guido van Rossum's avatar
Guido van Rossum committed
47

48

49
def join(s, *p):
50
    colon = _get_colon(s)
51 52 53 54 55
    path = s
    for t in p:
        if (not s) or isabs(t):
            path = t
            continue
56
        if t[:1] == colon:
57
            t = t[1:]
58 59 60 61
        if colon not in path:
            path = colon + path
        if path[-1:] != colon:
            path = path + colon
62 63 64
        path = path + t
    return path

65 66

def split(s):
67 68 69
    """Split a pathname into two parts: the directory leading up to the final
    bit, and the basename (the filename, without colons, in that directory).
    The result (s, t) is such that join(s, t) yields the original argument."""
70

71 72 73
    colon = _get_colon(s)
    if colon not in s: return s[:0], s
    col = 0
74
    for i in range(len(s)):
75 76 77 78
        if s[i:i+1] == colon: col = i + 1
    path, file = s[:col-1], s[col:]
    if path and not colon in path:
        path = path + colon
79
    return path, file
80

Guido van Rossum's avatar
Guido van Rossum committed
81 82

def splitext(p):
83 84 85 86
    if isinstance(p, bytes):
        return genericpath._splitext(p, b':', altsep, b'.')
    else:
        return genericpath._splitext(p, sep, altsep, extsep)
87
splitext.__doc__ = genericpath._splitext.__doc__
88

89
def splitdrive(p):
90 91 92 93 94 95
    """Split a pathname into a drive specification and the rest of the
    path.  Useful on DOS/Windows/NT; on the Mac, the drive is always
    empty (don't use the volume name -- it doesn't have the same
    syntactic and semantic oddities as DOS drive letters, such as there
    being a separate current directory per drive)."""

96
    return p[:0], p
97 98


99
# Short interfaces to split()
Guido van Rossum's avatar
Guido van Rossum committed
100

101 102
def dirname(s): return split(s)[0]
def basename(s): return split(s)[1]
Guido van Rossum's avatar
Guido van Rossum committed
103

Jack Jansen's avatar
Jack Jansen committed
104
def ismount(s):
Tim Peters's avatar
Tim Peters committed
105 106 107
    if not isabs(s):
        return False
    components = split(s)
108
    return len(components) == 2 and not components[1]
109

Guido van Rossum's avatar
Guido van Rossum committed
110
def islink(s):
111
    """Return true if the pathname refers to a symbolic link."""
Guido van Rossum's avatar
Guido van Rossum committed
112

113
    try:
Jack Jansen's avatar
Jack Jansen committed
114 115
        import Carbon.File
        return Carbon.File.ResolveAliasFile(s, 0)[2]
116 117
    except:
        return False
Guido van Rossum's avatar
Guido van Rossum committed
118

119 120 121 122 123 124 125 126 127 128 129 130
# Is `stat`/`lstat` a meaningful difference on the Mac?  This is safe in any
# case.

def lexists(path):
    """Test whether a path exists.  Returns True for broken symbolic links"""

    try:
        st = os.lstat(path)
    except os.error:
        return False
    return True

131
def expandvars(path):
132 133
    """Dummy to retain interface-compatibility with other operating systems."""
    return path
134

135

136 137 138
def expanduser(path):
    """Dummy to retain interface-compatibility with other operating systems."""
    return path
139

140 141
class norm_error(Exception):
    """Path cannot be normalized"""
142 143

def normpath(s):
144 145 146
    """Normalize a pathname.  Will return the same result for
    equivalent paths."""

147 148 149 150
    colon = _get_colon(s)

    if colon not in s:
        return colon + s
151

152
    comps = s.split(colon)
153 154
    i = 1
    while i < len(comps)-1:
155
        if not comps[i] and comps[i-1]:
156 157
            if i > 1:
                del comps[i-1:i+1]
158
                i = i - 1
159 160
            else:
                # best way to handle this is to raise an exception
161
                raise norm_error('Cannot use :: immediately after volume name')
162
        else:
163 164
            i = i + 1

165
    s = colon.join(comps)
166 167

    # remove trailing ":" except for ":" and "Volume:"
168
    if s[-1:] == colon and len(comps) > 2 and s != colon*len(s):
169
        s = s[:-1]
170 171
    return s

Guido van Rossum's avatar
Guido van Rossum committed
172
def abspath(path):
173
    """Return an absolute path."""
Guido van Rossum's avatar
Guido van Rossum committed
174
    if not isabs(path):
175 176 177 178 179
        if isinstance(path, bytes):
            cwd = os.getcwdb()
        else:
            cwd = os.getcwd()
        path = join(cwd, path)
Guido van Rossum's avatar
Guido van Rossum committed
180
    return normpath(path)
181 182

# realpath is a no-op on systems without islink support
183
def realpath(path):
Tim Peters's avatar
Tim Peters committed
184 185
    path = abspath(path)
    try:
Jack Jansen's avatar
Jack Jansen committed
186
        import Carbon.File
Tim Peters's avatar
Tim Peters committed
187 188 189 190
    except ImportError:
        return path
    if not path:
        return path
191 192 193
    colon = _get_colon(path)
    components = path.split(colon)
    path = components[0] + colon
Tim Peters's avatar
Tim Peters committed
194 195
    for c in components[1:]:
        path = join(path, c)
196 197 198 199
        try:
            path = Carbon.File.FSResolveAliasFile(path, 1)[0].as_pathname()
        except Carbon.File.Error:
            pass
Tim Peters's avatar
Tim Peters committed
200
    return path
201 202

supports_unicode_filenames = False