blob: a90d1053bc83d084e2e35867936fe7cf531e46d8 [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):
Serhiy Storchaka3deeeb02014-10-04 14:58:43 +030053 try:
54 colon = _get_colon(s)
55 path = s
Serhiy Storchaka5bfc03f2015-05-19 11:00:07 +030056 if not p:
57 path[:0] + colon #23780: Ensure compatible data type even if p is null.
Serhiy Storchaka3deeeb02014-10-04 14:58:43 +030058 for t in p:
59 if (not path) or isabs(t):
60 path = t
61 continue
62 if t[:1] == colon:
63 t = t[1:]
64 if colon not in path:
65 path = colon + path
66 if path[-1:] != colon:
67 path = path + colon
68 path = path + t
69 return path
70 except (TypeError, AttributeError, BytesWarning):
71 genericpath._check_arg_types('join', s, *p)
72 raise
Guido van Rossum217a5fa1990-12-26 15:40:07 +000073
Guido van Rossumb5e05e91991-01-01 18:10:40 +000074
Guido van Rossumb5e05e91991-01-01 18:10:40 +000075def split(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000076 """Split a pathname into two parts: the directory leading up to the final
77 bit, and the basename (the filename, without colons, in that directory).
78 The result (s, t) is such that join(s, t) yields the original argument."""
Guido van Rossumb5e05e91991-01-01 18:10:40 +000079
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000080 colon = _get_colon(s)
81 if colon not in s: return s[:0], s
82 col = 0
Guido van Rossum54f22ed2000-02-04 15:10:34 +000083 for i in range(len(s)):
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000084 if s[i:i+1] == colon: col = i + 1
85 path, file = s[:col-1], s[col:]
86 if path and not colon in path:
87 path = path + colon
Guido van Rossum54f22ed2000-02-04 15:10:34 +000088 return path, file
Guido van Rossumb5e05e91991-01-01 18:10:40 +000089
Guido van Rossuma48bf791996-07-23 02:28:32 +000090
91def splitext(p):
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000092 if isinstance(p, bytes):
93 return genericpath._splitext(p, b':', altsep, b'.')
94 else:
95 return genericpath._splitext(p, sep, altsep, extsep)
Guido van Rossumd8faa362007-04-27 19:54:29 +000096splitext.__doc__ = genericpath._splitext.__doc__
Guido van Rossum0ec31261995-08-10 18:09:16 +000097
98def splitdrive(p):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000099 """Split a pathname into a drive specification and the rest of the
100 path. Useful on DOS/Windows/NT; on the Mac, the drive is always
101 empty (don't use the volume name -- it doesn't have the same
102 syntactic and semantic oddities as DOS drive letters, such as there
103 being a separate current directory per drive)."""
104
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000105 return p[:0], p
Guido van Rossum0ec31261995-08-10 18:09:16 +0000106
107
Guido van Rossumc629d341992-11-05 10:43:02 +0000108# Short interfaces to split()
109
110def dirname(s): return split(s)[0]
111def basename(s): return split(s)[1]
112
Jack Jansen791f7d42003-01-15 22:45:48 +0000113def ismount(s):
Tim Peters2c60f7a2003-01-29 03:49:43 +0000114 if not isabs(s):
115 return False
116 components = split(s)
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000117 return len(components) == 2 and not components[1]
Guido van Rossumc629d341992-11-05 10:43:02 +0000118
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000119def islink(s):
Jack Jansen992d58b2002-04-22 13:55:43 +0000120 """Return true if the pathname refers to a symbolic link."""
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000121
Jack Jansen992d58b2002-04-22 13:55:43 +0000122 try:
Jack Jansen98fc6832003-02-27 23:18:46 +0000123 import Carbon.File
124 return Carbon.File.ResolveAliasFile(s, 0)[2]
Jack Jansen992d58b2002-04-22 13:55:43 +0000125 except:
126 return False
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000127
Johannes Gijsbersae882f72004-08-30 10:19:56 +0000128# Is `stat`/`lstat` a meaningful difference on the Mac? This is safe in any
129# case.
130
131def lexists(path):
132 """Test whether a path exists. Returns True for broken symbolic links"""
133
134 try:
135 st = os.lstat(path)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200136 except OSError:
Johannes Gijsbersae882f72004-08-30 10:19:56 +0000137 return False
138 return True
139
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000140def expandvars(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000141 """Dummy to retain interface-compatibility with other operating systems."""
142 return path
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000143
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000144
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000145def expanduser(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000146 """Dummy to retain interface-compatibility with other operating systems."""
147 return path
Guido van Rossum0ec31261995-08-10 18:09:16 +0000148
Neal Norwitz93cf79f2002-03-31 14:06:41 +0000149class norm_error(Exception):
150 """Path cannot be normalized"""
Guido van Rossumc629d341992-11-05 10:43:02 +0000151
152def normpath(s):
Jack Jansen2fc01092000-08-06 21:18:35 +0000153 """Normalize a pathname. Will return the same result for
154 equivalent paths."""
Jack Jansena68bfe21995-08-07 14:09:27 +0000155
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000156 colon = _get_colon(s)
Jack Jansen2fc01092000-08-06 21:18:35 +0000157
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000158 if colon not in s:
159 return colon + s
160
161 comps = s.split(colon)
Jack Jansen2fc01092000-08-06 21:18:35 +0000162 i = 1
163 while i < len(comps)-1:
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000164 if not comps[i] and comps[i-1]:
Jack Jansen2fc01092000-08-06 21:18:35 +0000165 if i > 1:
166 del comps[i-1:i+1]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000167 i = i - 1
Jack Jansen2fc01092000-08-06 21:18:35 +0000168 else:
169 # best way to handle this is to raise an exception
Collin Winterce36ad82007-08-30 01:19:48 +0000170 raise norm_error('Cannot use :: immediately after volume name')
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000171 else:
Jack Jansen2fc01092000-08-06 21:18:35 +0000172 i = i + 1
173
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000174 s = colon.join(comps)
Jack Jansen2fc01092000-08-06 21:18:35 +0000175
176 # remove trailing ":" except for ":" and "Volume:"
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000177 if s[-1:] == colon and len(comps) > 2 and s != colon*len(s):
Jack Jansen2fc01092000-08-06 21:18:35 +0000178 s = s[:-1]
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000179 return s
Guido van Rossum0ec31261995-08-10 18:09:16 +0000180
Guido van Rossume294cf61999-01-29 18:05:18 +0000181def abspath(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000182 """Return an absolute path."""
Guido van Rossume294cf61999-01-29 18:05:18 +0000183 if not isabs(path):
Florent Xicluna19b02d42010-03-08 12:25:35 +0000184 if isinstance(path, bytes):
185 cwd = os.getcwdb()
186 else:
187 cwd = os.getcwd()
188 path = join(cwd, path)
Guido van Rossume294cf61999-01-29 18:05:18 +0000189 return normpath(path)
Guido van Rossum83eeef42001-09-17 15:16:09 +0000190
191# realpath is a no-op on systems without islink support
Jack Jansen992d58b2002-04-22 13:55:43 +0000192def realpath(path):
Tim Peters8ac14952002-05-23 15:15:30 +0000193 path = abspath(path)
194 try:
Jack Jansen98fc6832003-02-27 23:18:46 +0000195 import Carbon.File
Brett Cannoncd171c82013-07-04 17:43:24 -0400196 except ImportError:
Tim Peters8ac14952002-05-23 15:15:30 +0000197 return path
198 if not path:
199 return path
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000200 colon = _get_colon(path)
201 components = path.split(colon)
202 path = components[0] + colon
Tim Peters8ac14952002-05-23 15:15:30 +0000203 for c in components[1:]:
204 path = join(path, c)
Florent Xicluna54467e02010-03-21 12:29:50 +0000205 try:
206 path = Carbon.File.FSResolveAliasFile(path, 1)[0].as_pathname()
207 except Carbon.File.Error:
208 pass
Tim Peters8ac14952002-05-23 15:15:30 +0000209 return path
Mark Hammond8696ebc2002-10-08 02:44:31 +0000210
Victor Stinnerccb706c2010-09-13 19:41:36 +0000211supports_unicode_filenames = True