blob: 1615d9122a128f0e7aecdc60b87fa356190bb85f [file] [log] [blame]
Guido van Rossum54f22ed2000-02-04 15:10:34 +00001"""Pathname and path-related operations for the Macintosh."""
Guido van Rossum217a5fa1990-12-26 15:40:07 +00002
Guido van Rossum5c1d2291998-03-03 21:49:01 +00003import os
Guido van Rossum217a5fa1990-12-26 15:40:07 +00004from stat import *
Guido van Rossumd8faa362007-04-27 19:54:29 +00005import genericpath
Thomas Wouters89f507f2006-12-13 04:49:30 +00006from genericpath import *
Guido van Rossum217a5fa1990-12-26 15:40:07 +00007
Skip Montanaro17ab1232001-01-24 06:27:27 +00008__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
9 "basename","dirname","commonprefix","getsize","getmtime",
Georg Brandlf0de6a12005-08-22 18:02:59 +000010 "getatime","getctime", "islink","exists","lexists","isdir","isfile",
Benjamin Petersond71ca412008-05-08 23:44:58 +000011 "expanduser","expandvars","normpath","abspath",
Skip Montanaro117910d2003-02-14 19:35:31 +000012 "curdir","pardir","sep","pathsep","defpath","altsep","extsep",
Martin v. Löwisbdec50f2004-06-08 08:29:33 +000013 "devnull","realpath","supports_unicode_filenames"]
Guido van Rossumb5e05e91991-01-01 18:10:40 +000014
Skip Montanaro117910d2003-02-14 19:35:31 +000015# strings representing various path-related bits and pieces
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000016# These are primarily for export; internally, they are hardcoded.
Skip Montanaro117910d2003-02-14 19:35:31 +000017curdir = ':'
18pardir = '::'
19extsep = '.'
20sep = ':'
21pathsep = '\n'
22defpath = ':'
23altsep = None
Martin v. Löwisbdec50f2004-06-08 08:29:33 +000024devnull = 'Dev:Null'
Skip Montanaro117910d2003-02-14 19:35:31 +000025
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000026def _get_colon(path):
27 if isinstance(path, bytes):
28 return b':'
29 else:
30 return ':'
31
Fred Drakeb4e460a2000-09-28 16:25:20 +000032# Normalize the case of a pathname. Dummy in Posix, but <s>.lower() here.
Guido van Rossum599f2ed1992-01-14 18:28:18 +000033
Fred Drakeb4e460a2000-09-28 16:25:20 +000034def normcase(path):
Ezio Melotti5a3ef5b2010-06-25 10:56:11 +000035 if not isinstance(path, (bytes, str)):
36 raise TypeError("normcase() argument must be str or bytes, "
37 "not '{}'".format(path.__class__.__name__))
Fred Drakeb4e460a2000-09-28 16:25:20 +000038 return path.lower()
Guido van Rossum599f2ed1992-01-14 18:28:18 +000039
40
Guido van Rossum217a5fa1990-12-26 15:40:07 +000041def isabs(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000042 """Return true if a path is absolute.
43 On the Mac, relative paths begin with a colon,
44 but as a special case, paths with no colons at all are also relative.
45 Anything else is absolute (the string up to the first colon is the
46 volume name)."""
47
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000048 colon = _get_colon(s)
49 return colon in s and s[:1] != colon
Guido van Rossum217a5fa1990-12-26 15:40:07 +000050
Guido van Rossumb5e05e91991-01-01 18:10:40 +000051
Barry Warsaw384d2491997-02-18 21:53:25 +000052def join(s, *p):
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000053 colon = _get_colon(s)
Guido van Rossum54f22ed2000-02-04 15:10:34 +000054 path = s
55 for t in p:
56 if (not s) or isabs(t):
57 path = t
58 continue
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000059 if t[:1] == colon:
Guido van Rossum54f22ed2000-02-04 15:10:34 +000060 t = t[1:]
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000061 if colon not in path:
62 path = colon + path
63 if path[-1:] != colon:
64 path = path + colon
Guido van Rossum54f22ed2000-02-04 15:10:34 +000065 path = path + t
66 return path
Guido van Rossum217a5fa1990-12-26 15:40:07 +000067
Guido van Rossumb5e05e91991-01-01 18:10:40 +000068
Guido van Rossumb5e05e91991-01-01 18:10:40 +000069def split(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000070 """Split a pathname into two parts: the directory leading up to the final
71 bit, and the basename (the filename, without colons, in that directory).
72 The result (s, t) is such that join(s, t) yields the original argument."""
Guido van Rossumb5e05e91991-01-01 18:10:40 +000073
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000074 colon = _get_colon(s)
75 if colon not in s: return s[:0], s
76 col = 0
Guido van Rossum54f22ed2000-02-04 15:10:34 +000077 for i in range(len(s)):
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000078 if s[i:i+1] == colon: col = i + 1
79 path, file = s[:col-1], s[col:]
80 if path and not colon in path:
81 path = path + colon
Guido van Rossum54f22ed2000-02-04 15:10:34 +000082 return path, file
Guido van Rossumb5e05e91991-01-01 18:10:40 +000083
Guido van Rossuma48bf791996-07-23 02:28:32 +000084
85def splitext(p):
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000086 if isinstance(p, bytes):
87 return genericpath._splitext(p, b':', altsep, b'.')
88 else:
89 return genericpath._splitext(p, sep, altsep, extsep)
Guido van Rossumd8faa362007-04-27 19:54:29 +000090splitext.__doc__ = genericpath._splitext.__doc__
Guido van Rossum0ec31261995-08-10 18:09:16 +000091
92def splitdrive(p):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000093 """Split a pathname into a drive specification and the rest of the
94 path. Useful on DOS/Windows/NT; on the Mac, the drive is always
95 empty (don't use the volume name -- it doesn't have the same
96 syntactic and semantic oddities as DOS drive letters, such as there
97 being a separate current directory per drive)."""
98
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000099 return p[:0], p
Guido van Rossum0ec31261995-08-10 18:09:16 +0000100
101
Guido van Rossumc629d341992-11-05 10:43:02 +0000102# Short interfaces to split()
103
104def dirname(s): return split(s)[0]
105def basename(s): return split(s)[1]
106
Jack Jansen791f7d42003-01-15 22:45:48 +0000107def ismount(s):
Tim Peters2c60f7a2003-01-29 03:49:43 +0000108 if not isabs(s):
109 return False
110 components = split(s)
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000111 return len(components) == 2 and not components[1]
Guido van Rossumc629d341992-11-05 10:43:02 +0000112
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000113def islink(s):
Jack Jansen992d58b2002-04-22 13:55:43 +0000114 """Return true if the pathname refers to a symbolic link."""
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000115
Jack Jansen992d58b2002-04-22 13:55:43 +0000116 try:
Jack Jansen98fc6832003-02-27 23:18:46 +0000117 import Carbon.File
118 return Carbon.File.ResolveAliasFile(s, 0)[2]
Jack Jansen992d58b2002-04-22 13:55:43 +0000119 except:
120 return False
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000121
Johannes Gijsbersae882f72004-08-30 10:19:56 +0000122# Is `stat`/`lstat` a meaningful difference on the Mac? This is safe in any
123# case.
124
125def lexists(path):
126 """Test whether a path exists. Returns True for broken symbolic links"""
127
128 try:
129 st = os.lstat(path)
130 except os.error:
131 return False
132 return True
133
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000134def expandvars(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000135 """Dummy to retain interface-compatibility with other operating systems."""
136 return path
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000137
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000138
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000139def expanduser(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000140 """Dummy to retain interface-compatibility with other operating systems."""
141 return path
Guido van Rossum0ec31261995-08-10 18:09:16 +0000142
Neal Norwitz93cf79f2002-03-31 14:06:41 +0000143class norm_error(Exception):
144 """Path cannot be normalized"""
Guido van Rossumc629d341992-11-05 10:43:02 +0000145
146def normpath(s):
Jack Jansen2fc01092000-08-06 21:18:35 +0000147 """Normalize a pathname. Will return the same result for
148 equivalent paths."""
Jack Jansena68bfe21995-08-07 14:09:27 +0000149
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000150 colon = _get_colon(s)
Jack Jansen2fc01092000-08-06 21:18:35 +0000151
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000152 if colon not in s:
153 return colon + s
154
155 comps = s.split(colon)
Jack Jansen2fc01092000-08-06 21:18:35 +0000156 i = 1
157 while i < len(comps)-1:
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000158 if not comps[i] and comps[i-1]:
Jack Jansen2fc01092000-08-06 21:18:35 +0000159 if i > 1:
160 del comps[i-1:i+1]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000161 i = i - 1
Jack Jansen2fc01092000-08-06 21:18:35 +0000162 else:
163 # best way to handle this is to raise an exception
Collin Winterce36ad82007-08-30 01:19:48 +0000164 raise norm_error('Cannot use :: immediately after volume name')
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000165 else:
Jack Jansen2fc01092000-08-06 21:18:35 +0000166 i = i + 1
167
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000168 s = colon.join(comps)
Jack Jansen2fc01092000-08-06 21:18:35 +0000169
170 # remove trailing ":" except for ":" and "Volume:"
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000171 if s[-1:] == colon and len(comps) > 2 and s != colon*len(s):
Jack Jansen2fc01092000-08-06 21:18:35 +0000172 s = s[:-1]
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000173 return s
Guido van Rossum0ec31261995-08-10 18:09:16 +0000174
Guido van Rossume294cf61999-01-29 18:05:18 +0000175def abspath(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000176 """Return an absolute path."""
Guido van Rossume294cf61999-01-29 18:05:18 +0000177 if not isabs(path):
Florent Xicluna19b02d42010-03-08 12:25:35 +0000178 if isinstance(path, bytes):
179 cwd = os.getcwdb()
180 else:
181 cwd = os.getcwd()
182 path = join(cwd, path)
Guido van Rossume294cf61999-01-29 18:05:18 +0000183 return normpath(path)
Guido van Rossum83eeef42001-09-17 15:16:09 +0000184
185# realpath is a no-op on systems without islink support
Jack Jansen992d58b2002-04-22 13:55:43 +0000186def realpath(path):
Tim Peters8ac14952002-05-23 15:15:30 +0000187 path = abspath(path)
188 try:
Jack Jansen98fc6832003-02-27 23:18:46 +0000189 import Carbon.File
Tim Peters8ac14952002-05-23 15:15:30 +0000190 except ImportError:
191 return path
192 if not path:
193 return path
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000194 colon = _get_colon(path)
195 components = path.split(colon)
196 path = components[0] + colon
Tim Peters8ac14952002-05-23 15:15:30 +0000197 for c in components[1:]:
198 path = join(path, c)
Florent Xicluna54467e02010-03-21 12:29:50 +0000199 try:
200 path = Carbon.File.FSResolveAliasFile(path, 1)[0].as_pathname()
201 except Carbon.File.Error:
202 pass
Tim Peters8ac14952002-05-23 15:15:30 +0000203 return path
Mark Hammond8696ebc2002-10-08 02:44:31 +0000204
Victor Stinnerccb706c2010-09-13 19:41:36 +0000205supports_unicode_filenames = True