blob: b0132aef0be33c60336eeb15a9b976aa5df31087 [file] [log] [blame]
Jack Jansen58fc91f2002-12-17 23:28:24 +00001"""macfs - Pure Python module designed to be backward compatible with
2macfs and MACFS.
3"""
4import sys
Jack Jansen6dd561b2002-12-26 21:09:39 +00005import struct
6import Carbon.Res
7import Carbon.File
8import Nav
Jack Jansen58fc91f2002-12-17 23:28:24 +00009
10# First step: ensure we also emulate the MACFS module, which contained
11# all the constants
12
13sys.modules['MACFS'] = sys.modules[__name__]
14
15# Import all those constants
Jack Jansen4235e712002-12-19 23:26:07 +000016from Carbon.Files import *
17from Carbon.Folders import *
Jack Jansen58fc91f2002-12-17 23:28:24 +000018
19# For some obscure historical reason these are here too:
20READ = 1
21WRITE = 2
22smAllScripts = -3
23
Jack Jansen2d0909b2003-01-15 22:36:16 +000024#
25# Find the epoch conversion for file dates in a way that works on OS9 and OSX
26import time
27if time.gmtime(0)[0] == 1970:
28 _EPOCHCONVERT = -((1970-1904)*365 + 17) * (24*60*60) + 0x100000000L
29 def _utc2time(utc):
30 t = utc[1] + _EPOCHCONVERT
31 return int(t)
32 def _time2utc(t):
33 t = t - _EPOCHCONVERT
34 if t < -0x7fffffff:
35 t = t + 0x10000000L
36 return (0, int(t), 0)
37else:
38 def _utc2time(utc): return utc[1]
39 def _time2utc(t): return (0, t, 0)
40
Jack Jansen4235e712002-12-19 23:26:07 +000041# The old name of the error object:
42error = Carbon.File.Error
Jack Jansen58fc91f2002-12-17 23:28:24 +000043
Jack Jansen6dd561b2002-12-26 21:09:39 +000044#
45# The various objects macfs used to export. We override them here, because some
46# of the method names are subtly different.
47#
Jack Jansen58fc91f2002-12-17 23:28:24 +000048class FSSpec(Carbon.File.FSSpec):
Jack Jansen4235e712002-12-19 23:26:07 +000049 def as_fsref(self):
Jack Jansen58fc91f2002-12-17 23:28:24 +000050 return FSRef(self)
51
52 def NewAlias(self, src=None):
Jack Jansen4235e712002-12-19 23:26:07 +000053 return Alias(Carbon.File.NewAlias(src, self))
Jack Jansen58fc91f2002-12-17 23:28:24 +000054
55 def GetCreatorType(self):
56 finfo = self.FSpGetFInfo()
Jack Jansen4235e712002-12-19 23:26:07 +000057 return finfo.Creator, finfo.Type
Jack Jansen58fc91f2002-12-17 23:28:24 +000058
59 def SetCreatorType(self, ctor, tp):
60 finfo = self.FSpGetFInfo()
Jack Jansen4235e712002-12-19 23:26:07 +000061 finfo.Creator = ctor
62 finfo.Type = tp
Jack Jansen58fc91f2002-12-17 23:28:24 +000063 self.FSpSetFInfo(finfo)
64
65 def GetFInfo(self):
66 return self.FSpGetFInfo()
67
68 def SetFInfo(self, info):
69 return self.FSpSetFInfo(info)
70
71 def GetDates(self):
Jack Jansen2d0909b2003-01-15 22:36:16 +000072 catInfoFlags = kFSCatInfoCreateDate|kFSCatInfoContentMod|kFSCatInfoBackupDate
73 catinfo, d1, d2, d3 = FSRef(self).FSGetCatalogInfo(catInfoFlags)
74 cdate = catinfo.createDate
75 mdate = catinfo.contentModDate
76 bdate = catinfo.backupDate
77 return _utc2time(cdate), _utc2time(mdate), _utc2time(bdate)
Jack Jansen58fc91f2002-12-17 23:28:24 +000078
Jack Jansen2d0909b2003-01-15 22:36:16 +000079 def SetDates(self, cdate, mdate, bdate):
80 catInfoFlags = kFSCatInfoCreateDate|kFSCatInfoContentMod|kFSCatInfoBackupDate
81 catinfo = Carbon.File.FSCatalogInfo(
82 createDate = _time2utc(cdate),
83 contentModDate = _time2utc(mdate),
84 backupDate = _time2utc(bdate))
85 FSRef(self).FSSetCatalogInfo(catInfoFlags, catinfo)
Jack Jansen58fc91f2002-12-17 23:28:24 +000086
87class FSRef(Carbon.File.FSRef):
Jack Jansen4235e712002-12-19 23:26:07 +000088 def as_fsspec(self):
Jack Jansen58fc91f2002-12-17 23:28:24 +000089 return FSSpec(self)
90
91class Alias(Carbon.File.Alias):
92
Jack Jansen58fc91f2002-12-17 23:28:24 +000093 def GetInfo(self, index):
94 return self.GetAliasInfo(index)
95
96 def Update(self, *args):
Jack Jansen27d19c42003-01-08 16:32:29 +000097 pass # print "Alias.Update not yet implemented"
Jack Jansen4235e712002-12-19 23:26:07 +000098
99 def Resolve(self, src=None):
Jack Jansen315e9be2002-12-26 20:46:54 +0000100 fss, changed = self.ResolveAlias(src)
101 return FSSpec(fss), changed
Jack Jansen4235e712002-12-19 23:26:07 +0000102
103from Carbon.File import FInfo
Jack Jansen6dd561b2002-12-26 21:09:39 +0000104
105# Backward-compatible type names:
Jack Jansen58fc91f2002-12-17 23:28:24 +0000106FSSpecType = FSSpec
107FSRefType = FSRef
108AliasType = Alias
109FInfoType = FInfo
110
Jack Jansen6dd561b2002-12-26 21:09:39 +0000111# Global functions:
Jack Jansen58fc91f2002-12-17 23:28:24 +0000112def ResolveAliasFile(fss, chain=1):
Jack Jansen315e9be2002-12-26 20:46:54 +0000113 fss, isdir, isalias = Carbon.File.ResolveAliasFile(fss, chain)
114 return FSSpec(fss), isdir, isalias
Jack Jansen58fc91f2002-12-17 23:28:24 +0000115
116def RawFSSpec(data):
117 return FSSpec(rawdata=data)
118
119def RawAlias(data):
120 return Alias(rawdata=data)
121
122def FindApplication(*args):
123 raise NotImplementedError, "FindApplication no longer implemented"
124
125def NewAliasMinimalFromFullPath(path):
Jack Jansen315e9be2002-12-26 20:46:54 +0000126 return Alias(Carbon.File.NewAliasMinimalFromFullPath(path, '', ''))
Jack Jansen4235e712002-12-19 23:26:07 +0000127
Jack Jansen6dd561b2002-12-26 21:09:39 +0000128# Another global function:
129from Carbon.Folder import FindFolder
130
131#
132# Finally the old Standard File routine emulators.
133#
134
135_movablemodal = 0
136_curfolder = None
137
138def _mktypelist(typelist):
139 # Workaround for OSX typeless files:
140 if 'TEXT' in typelist and not '\0\0\0\0' in typelist:
141 typelist = typelist + ('\0\0\0\0',)
142 if not typelist:
143 return None
144 data = 'Pyth' + struct.pack("hh", 0, len(typelist))
145 for type in typelist:
146 data = data+type
147 return Carbon.Res.Handle(data)
148
149def StandardGetFile(*typelist):
150 """Ask for an input file, optionally specifying 4-char file types that are
151 allowable"""
152 return apply(PromptGetFile, (None,)+typelist)
153
154def PromptGetFile(prompt, *typelist):
155 """Ask for an input file giving the user a prompt message. Optionally you can
156 specifying 4-char file types that are allowable"""
157 args = {}
158 flags = 0x56
159 typehandle = _mktypelist(typelist)
160 if typehandle:
161 args['typeList'] = typehandle
162 else:
163 flags = flags | 0x01
164 if prompt:
165 args['message'] = prompt
166 args['preferenceKey'] = 'PyMC'
167 if _movablemodal:
168 args['eventProc'] = None
169 args['dialogOptionFlags'] = flags
170 _handleSetFolder(args)
171 try:
172 rr = Nav.NavChooseFile(args)
173 good = 1
174 except Nav.error, arg:
175 if arg[0] != -128: # userCancelledErr
176 raise Nav.error, arg
177 good = 0
178 fss = None
179 else:
180 if rr.selection:
181 fss = FSSpec(rr.selection[0])
182 else:
183 fss = None
184 good = 0
185## if typehandle:
186## typehandle.DisposeHandle()
187 return fss, good
188
189def StandardPutFile(prompt, default=None):
190 """Ask the user for an output file, with a prompt. Optionally you cn supply a
191 default output filename"""
192 args = {}
193 flags = 0x07
194 if prompt:
195 args['message'] = prompt
196 args['preferenceKey'] = 'PyMC'
197 if _movablemodal:
198 args['eventProc'] = None
199 if default:
200 args['savedFileName'] = default
201 args['dialogOptionFlags'] = flags
202 _handleSetFolder(args)
203 try:
204 rr = Nav.NavPutFile(args)
205 good = 1
206 except Nav.error, arg:
207 if arg[0] != -128: # userCancelledErr
208 raise Nav.error, arg
209 good = 0
210 fss = None
211 else:
212 fss = FSSpec(rr.selection[0])
213 return fss, good
214
215def SetFolder(folder):
216 global _curfolder
217 if _curfolder:
218 rv = _curfolder
219 else:
220 rv = None
221 _curfolder = FSSpec(folder)
222 return rv
223
224def _handleSetFolder(args):
225 global _curfolder
226 if not _curfolder:
227 return
228 import aepack
229 fss = _curfolder
230 aedesc = aepack.pack(fss)
231 args['defaultLocation'] = aedesc
232 _curfolder = None
233
234def GetDirectory(prompt=None):
235 """Ask the user to select a folder. Optionally you can give a prompt."""
236 args = {}
237 flags = 0x17
238 if prompt:
239 args['message'] = prompt
240 args['preferenceKey'] = 'PyMC'
241 if _movablemodal:
242 args['eventProc'] = None
243 args['dialogOptionFlags'] = flags
244 _handleSetFolder(args)
245 try:
246 rr = Nav.NavChooseFolder(args)
247 good = 1
248 except Nav.error, arg:
249 if arg[0] != -128: # userCancelledErr
250 raise Nav.error, arg
251 good = 0
252 fss = None
253 else:
254 fss = FSSpec(rr.selection[0])
255 return fss, good
256