Bump version to 0.9.1.
[python/dscho.git] / Mac / Contrib / PythonScript / getaete.py
blob14beb323cc38f3a13313743f9c61184324743f3a
1 """
2 Produces a 3 dictionaries from application aete's
3 to be read by PythonScript
5 v.02 january 31, 1998 added support for inheriting suites from aeut
6 v.03 february 16, 1998 changes to identify
7 v.04 february 26, 1998 simplified decode
8 v.05 23/04/98 simplified _launch
10 """
11 import baetools
12 import macpath
13 import sys
14 import os
15 import MacOS
16 import StringIO
17 import types
18 from MACFS import *
19 import macfs
20 import string
21 from Res import *
22 import struct
24 # for testing only
25 app ='CSOm' #'ezVu'# 'nwSP'#MACS'#
27 #Restrict the application suites to the dialect we want to use.
28 LANG = 0 # 0 = English, 1 = French, 11 = Japanese
29 lang = {0:'English', 1:'French', 11:'Japanese'}
31 #The following are neaded to open the application aete
32 kASAppleScriptSuite = 'ascr'
33 kGetAETE = 'gdte'
34 attributes = {}
35 arguments = {}
37 class AETE(baetools.TalkTo):
38 pass
40 def Getaete(app):
41 try:
42 data = openaete(app)
43 except MacOS.Error, msg:
44 if msg[0] == -609:
45 _launch(app)
46 data = openaete(app)
47 data = decode(data['----'].data)
48 data = compileaete(data)
49 return data
52 def decode(data):
53 """Decode an aete into a python data structure"""
54 f = StringIO.StringIO(data)
55 aete = generic(getaete, f)
56 return aete
58 def simplify(item):
59 """Recursively replace singleton tuples by their constituent item"""
60 if type(item) is types.ListType:
61 return map(simplify, item)
62 elif type(item) == types.TupleType and len(item) == 2:
63 return simplify(item[1])
64 else:
65 return item
68 ## Here follows the aete resource decoder.
69 ## It is presented bottom-up instead of top-down because there are direct
70 ## references to the lower-level part-decoders from the high-level part-decoders.
72 def getflag(f, *args):
73 m = ''
74 c = f.read(2)
75 print `c`
76 if not c:
77 raise EOFError, 'in getflag' + str(args)
78 for n in c:
79 m = m + `ord(n)`
81 def getbyte(f, *args):
82 c = f.read(1)
83 if not c:
84 raise EOFError, 'in getbyte' + str(args)
85 return ord(c)
87 def getword(f, *args):
88 getalign(f)
89 s = f.read(2)
90 if len(s) < 2:
91 raise EOFError, 'in getword' + str(args)
92 return (ord(s[0])<<8) | ord(s[1])
94 def getlong(f, *args):
95 getalign(f)
96 s = f.read(4)
97 if len(s) < 4:
98 raise EOFError, 'in getlong' + str(args)
99 return (ord(s[0])<<24) | (ord(s[1])<<16) | (ord(s[2])<<8) | ord(s[3])
101 def getostype(f, *args):
102 getalign(f)
103 s = f.read(4)
104 if len(s) < 4:
105 raise EOFError, 'in getostype' + str(args)
106 return s
108 def getpstr(f, *args):
109 c = f.read(1)
110 if len(c) < 1:
111 raise EOFError, 'in getpstr[1]' + str(args)
112 nbytes = ord(c)
113 if nbytes == 0: return ''
114 s = f.read(nbytes)
115 if len(s) < nbytes:
116 raise EOFError, 'in getpstr[2]' + str(args)
117 return s
119 def getalign(f):
120 if f.tell() & 1:
121 c = f.read(1)
122 ##if c <> '\0':
123 ## print 'align:', `c`
125 def getlist(f, description, getitem):
126 count = getword(f)
127 list = []
128 for i in range(count):
129 list.append(generic(getitem, f))
130 getalign(f)
131 return list
133 def alt_generic(what, f, *args):
134 print "generic", `what`, args
135 res = vageneric(what, f, args)
136 print '->', `res`
137 return res
139 def generic(what, f, *args):
140 if type(what) == types.FunctionType:
141 return apply(what, (f,) + args)
142 if type(what) == types.ListType:
143 record = []
144 for thing in what:
145 item = apply(generic, thing[:1] + (f,) + thing[1:])
146 record.append(item)
147 return record
148 return "BAD GENERIC ARGS: %s" % `what`
150 getdata = [
151 (getostype, "type"),
152 (getpstr, "description"),
153 (getword, "flags")
155 getargument = [
156 (getpstr, "name"),
157 (getostype, "keyword"),
158 (getdata, "what")
160 getevent = [
161 (getpstr, "name"),
162 (getpstr, "description"),
163 (getostype, "suite code"),
164 (getostype, "event code"),
165 (getdata, "returns"),
166 (getdata, "accepts"),
167 (getlist, "optional arguments", getargument)
169 getproperty = [
170 (getpstr, "name"),
171 (getostype, "code"),
172 (getdata, "what")
174 getelement = [
175 (getostype, "type"),
176 (getlist, "keyform", getostype)
178 getclass = [
179 (getpstr, "name"),
180 (getostype, "class code"),
181 (getpstr, "description"),
182 (getlist, "properties", getproperty),
183 (getlist, "elements", getelement)
185 getcomparison = [
186 (getpstr, "operator name"),
187 (getostype, "operator ID"),
188 (getpstr, "operator comment"),
190 getenumerator = [
191 (getpstr, "enumerator name"),
192 (getostype, "enumerator ID"),
193 (getpstr, "enumerator comment")
195 getenumeration = [
196 (getostype, "enumeration ID"),
197 (getlist, "enumerator", getenumerator)
199 getsuite = [
200 (getpstr, "suite name"),
201 (getpstr, "suite description"),
202 (getostype, "suite ID"),
203 (getword, "suite level"),
204 (getword, "suite version"),
205 (getlist, "events", getevent),
206 (getlist, "classes", getclass),
207 (getlist, "comparisons", getcomparison),
208 (getlist, "enumerations", getenumeration)
210 getaete = [
211 (getbyte, "major version in BCD"),
212 (getbyte, "minor version in BCD"),
213 (getword, "language code"),
214 (getword, "script code"),
215 (getlist, "suites", getsuite)
218 def compileaete(aete):
219 """Generate dictionary for a full aete resource."""
220 [major, minor, language, script, suites] = aete
221 suitedict = {}
222 gsuites = openaeut()
223 for gsuite in gsuites:
224 if gsuite[0] == 'AppleScript Suite':
225 suite = gsuite
226 suite = compilesuite(suite)
227 suitedict[identify(suite[0])] = suite[1:]
228 for suite in suites:
229 if language == LANG:
230 suitecode = suite[2]
231 if suite[5] == []:
232 for gsuite in gsuites:
233 if suitecode == gsuite[2]:
234 suite = gsuite
235 suite = compilesuite(suite)
236 suitedict[identify(suite[0])] = suite[1:]
237 suitedict = combinesuite(suitedict)
238 return suitedict
240 def compilesuite(suite):
241 """Generate dictionary for a single suite"""
242 [name, desc, code, level, version, events, classes, comps, enums] = suite
243 eventdict ={}
244 classdict = {}
245 enumdict ={}
246 for event in events:
247 if event[6]:
248 for ev in event[6]:
249 ev[0] = identify(ev[:2])
250 eventdict[identify(event[:2])] = event[1:]
251 for klass in classes:
252 if klass[3]:
253 for kl in klass[3]:
254 kl[0] = identify(kl[:2])
255 classdict[identify(klass[:2])] = klass[1:]
256 for enum in enums:
257 enumdict[enum[0]] = enum[1]
258 return name, eventdict, classdict, enumdict
260 def combinesuite(suite):
261 """Combines suite dictionaries to seperate event, class, enumeration dictionaries
264 suitelist = []
265 eventDict ={}
266 classDict ={}
267 enumDict ={}
268 for value in suite.values():
269 for key in value[0].keys():
270 val = value[0][key]
271 eventDict[key] = val
272 for key in value[1].keys():
273 val = value[1][key]
274 if key in classDict.keys():
275 nval = classDict[key][2]
276 val[2] = val[2] + nval
277 classDict[key] = val
278 for key in value[2].keys():
279 val = value[2][key]
280 enumDict[key] = val
281 return eventDict, classDict, enumDict
284 illegal_ids = [ "for", "in", "from", "and", "or", "not", "print", "class", "return",
285 "def", "name", 'data' ]
287 def identify(str):
288 """Turn any string into an identifier:
289 - replace space by _
290 - remove ',' and '-'
291 capitalise
293 if not str[0]:
294 if str[1] == 'c@#!':
295 return "Every"
296 else:
297 return 'Any'
298 rv = string.replace(str[0], ' ', '_')
299 rv = string.replace(rv, '-', '')
300 rv = string.replace(rv, ',', '')
301 rv = string.capitalize(rv)
302 return rv
305 def openaete(app):
306 """open and read the aete of the target application"""
307 arguments['----'] = LANG
308 _aete = AETE(app)
309 _reply, _arguments, _attributes = _aete.send(kASAppleScriptSuite, kGetAETE, arguments, attributes)
310 if _arguments.has_key('errn'):
311 raise baetools.Error, baetools.decodeerror(_arguments)
312 return _arguments
314 def openaeut():
315 """Open and read a aeut file.
316 XXXXX This has been temporarily hard coded until a Python aeut is written XXXX"""
318 fullname = dialect
319 rf = OpenRFPerm(fullname, 0, 1)
320 try:
321 UseResFile(rf)
322 resources = []
323 for i in range(Count1Resources('aeut')):
324 res = Get1IndResource('aeut', 1+i)
325 resources.append(res)
326 for res in resources:
327 data = res.data
328 data = decode(data)[4]
329 finally:
330 CloseResFile(rf)
331 return data
333 def dialect():
334 """find the correct Dialect file"""
336 dialect = lang[LANG] + " Dialect"
337 try:
338 ##System 8
339 vRefNum, dirID = macfs.FindFolder(kOnSystemDisk, kScriptingAdditionsFolderType, 0)
340 fss = macfs.FSSpec((vRefNum, dirID, ''))
341 fss = fss.as_pathname()
342 except macfs.error:
343 ##Sytem 7
344 vRefNum, dirID = macfs.FindFolder(kOnSystemDisk, kExtensionFolderType, 0)
345 fss = macfs.FSSpec((vRefNum, dirID, ''))
346 fss = fss.as_pathname()
347 fss = macpath.join(fss, "Scripting Additions")
348 fss = macpath.join(fss, "Dialect")
349 fss = macpath.join(fss, dialect)
350 return fss
353 #def openosax():
354 # """Open and read the aetes of osaxen in the scripting additions folder"""
356 # # System 7.x
357 # aete = []
358 # vRefNum, dirID = macfs.FindFolder(kOnSystemDisk, kExtensionFolderType, 0)
359 # fss = macfs.FSSpec((vRefNum, dirID, ''))
360 # fss = fss.as_pathname()
361 # osax = macpath.join(fss, "Scripting Additions")
362 # for file in os.listdir(osax):
363 # fullname = macpath.join(osax, file)
364 # print fullname
365 # rf = OpenRFPerm(fullname, 0, 1)
366 # try:
367 # UseResFile(rf)
368 # resources = []
369 # for i in range(Count1Resources('aete')):
370 # res = Get1IndResource('aete', 1+i)
371 # resources.append(res)
372 # for res in resources:
373 # data = res.data
374 # data = decode(data)[4]
375 # finally:
376 # CloseResFile(rf)
377 # aete.append(data)
378 # print data
381 #The following should be replaced by direct access to a python 'aeut'
383 def _launch(appfile):
384 """Open a file thru the finder. Specify file by name or fsspec"""
386 # from PythonScript import PyScript
387 import baetypes
388 _finder = AETE('MACS')
389 parameters ={}
390 parameters['----'] = eval("baetypes.ObjectSpecifier('%s', '%s', %s)" % ('appf', 'ID ', `appfile`))
391 _reply, _arguments, _attributes = _finder.send( 'aevt', 'odoc', parameters , attributes = {})
392 if _arguments.has_key('errn'):
393 raise baetools.Error, baetools.decodeerror(_arguments)
394 # XXXX Optionally decode result
395 if _arguments.has_key('----'):
396 return _arguments['----']
400 if __name__ == '__main__':
401 # import profile
402 # profile.run('Getaete(app)', 'Getaeteprof')
403 Getaete(app)
404 # openosax()
405 # openaete('ascr')
406 # sys.exit(1)