diff options
Diffstat (limited to 'Mac/Contrib/PythonScript/getaete.py')
-rw-r--r-- | Mac/Contrib/PythonScript/getaete.py | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/Mac/Contrib/PythonScript/getaete.py b/Mac/Contrib/PythonScript/getaete.py new file mode 100644 index 0000000..14beb32 --- /dev/null +++ b/Mac/Contrib/PythonScript/getaete.py @@ -0,0 +1,406 @@ +""" +Produces a 3 dictionaries from application aete's +to be read by PythonScript + +v.02 january 31, 1998 added support for inheriting suites from aeut +v.03 february 16, 1998 changes to identify +v.04 february 26, 1998 simplified decode +v.05 23/04/98 simplified _launch + +""" +import baetools +import macpath +import sys +import os +import MacOS +import StringIO +import types +from MACFS import * +import macfs +import string +from Res import * +import struct + +# for testing only +app ='CSOm' #'ezVu'# 'nwSP'#MACS'# + +#Restrict the application suites to the dialect we want to use. +LANG = 0 # 0 = English, 1 = French, 11 = Japanese +lang = {0:'English', 1:'French', 11:'Japanese'} + +#The following are neaded to open the application aete +kASAppleScriptSuite = 'ascr' +kGetAETE = 'gdte' +attributes = {} +arguments = {} + +class AETE(baetools.TalkTo): + pass + +def Getaete(app): + try: + data = openaete(app) + except MacOS.Error, msg: + if msg[0] == -609: + _launch(app) + data = openaete(app) + data = decode(data['----'].data) + data = compileaete(data) + return data + + +def decode(data): + """Decode an aete into a python data structure""" + f = StringIO.StringIO(data) + aete = generic(getaete, f) + return aete + +def simplify(item): + """Recursively replace singleton tuples by their constituent item""" + if type(item) is types.ListType: + return map(simplify, item) + elif type(item) == types.TupleType and len(item) == 2: + return simplify(item[1]) + else: + return item + + +## Here follows the aete resource decoder. +## It is presented bottom-up instead of top-down because there are direct +## references to the lower-level part-decoders from the high-level part-decoders. +# +def getflag(f, *args): + m = '' + c = f.read(2) + print `c` + if not c: + raise EOFError, 'in getflag' + str(args) + for n in c: + m = m + `ord(n)` + +def getbyte(f, *args): + c = f.read(1) + if not c: + raise EOFError, 'in getbyte' + str(args) + return ord(c) + +def getword(f, *args): + getalign(f) + s = f.read(2) + if len(s) < 2: + raise EOFError, 'in getword' + str(args) + return (ord(s[0])<<8) | ord(s[1]) + +def getlong(f, *args): + getalign(f) + s = f.read(4) + if len(s) < 4: + raise EOFError, 'in getlong' + str(args) + return (ord(s[0])<<24) | (ord(s[1])<<16) | (ord(s[2])<<8) | ord(s[3]) + +def getostype(f, *args): + getalign(f) + s = f.read(4) + if len(s) < 4: + raise EOFError, 'in getostype' + str(args) + return s + +def getpstr(f, *args): + c = f.read(1) + if len(c) < 1: + raise EOFError, 'in getpstr[1]' + str(args) + nbytes = ord(c) + if nbytes == 0: return '' + s = f.read(nbytes) + if len(s) < nbytes: + raise EOFError, 'in getpstr[2]' + str(args) + return s + +def getalign(f): + if f.tell() & 1: + c = f.read(1) + ##if c <> '\0': + ## print 'align:', `c` + +def getlist(f, description, getitem): + count = getword(f) + list = [] + for i in range(count): + list.append(generic(getitem, f)) + getalign(f) + return list + +def alt_generic(what, f, *args): + print "generic", `what`, args + res = vageneric(what, f, args) + print '->', `res` + return res + +def generic(what, f, *args): + if type(what) == types.FunctionType: + return apply(what, (f,) + args) + if type(what) == types.ListType: + record = [] + for thing in what: + item = apply(generic, thing[:1] + (f,) + thing[1:]) + record.append(item) + return record + return "BAD GENERIC ARGS: %s" % `what` + +getdata = [ + (getostype, "type"), + (getpstr, "description"), + (getword, "flags") + ] +getargument = [ + (getpstr, "name"), + (getostype, "keyword"), + (getdata, "what") + ] +getevent = [ + (getpstr, "name"), + (getpstr, "description"), + (getostype, "suite code"), + (getostype, "event code"), + (getdata, "returns"), + (getdata, "accepts"), + (getlist, "optional arguments", getargument) + ] +getproperty = [ + (getpstr, "name"), + (getostype, "code"), + (getdata, "what") + ] +getelement = [ + (getostype, "type"), + (getlist, "keyform", getostype) + ] +getclass = [ + (getpstr, "name"), + (getostype, "class code"), + (getpstr, "description"), + (getlist, "properties", getproperty), + (getlist, "elements", getelement) + ] +getcomparison = [ + (getpstr, "operator name"), + (getostype, "operator ID"), + (getpstr, "operator comment"), + ] +getenumerator = [ + (getpstr, "enumerator name"), + (getostype, "enumerator ID"), + (getpstr, "enumerator comment") + ] +getenumeration = [ + (getostype, "enumeration ID"), + (getlist, "enumerator", getenumerator) + ] +getsuite = [ + (getpstr, "suite name"), + (getpstr, "suite description"), + (getostype, "suite ID"), + (getword, "suite level"), + (getword, "suite version"), + (getlist, "events", getevent), + (getlist, "classes", getclass), + (getlist, "comparisons", getcomparison), + (getlist, "enumerations", getenumeration) + ] +getaete = [ + (getbyte, "major version in BCD"), + (getbyte, "minor version in BCD"), + (getword, "language code"), + (getword, "script code"), + (getlist, "suites", getsuite) + ] + +def compileaete(aete): + """Generate dictionary for a full aete resource.""" + [major, minor, language, script, suites] = aete + suitedict = {} + gsuites = openaeut() + for gsuite in gsuites: + if gsuite[0] == 'AppleScript Suite': + suite = gsuite + suite = compilesuite(suite) + suitedict[identify(suite[0])] = suite[1:] + for suite in suites: + if language == LANG: + suitecode = suite[2] + if suite[5] == []: + for gsuite in gsuites: + if suitecode == gsuite[2]: + suite = gsuite + suite = compilesuite(suite) + suitedict[identify(suite[0])] = suite[1:] + suitedict = combinesuite(suitedict) + return suitedict + +def compilesuite(suite): + """Generate dictionary for a single suite""" + [name, desc, code, level, version, events, classes, comps, enums] = suite + eventdict ={} + classdict = {} + enumdict ={} + for event in events: + if event[6]: + for ev in event[6]: + ev[0] = identify(ev[:2]) + eventdict[identify(event[:2])] = event[1:] + for klass in classes: + if klass[3]: + for kl in klass[3]: + kl[0] = identify(kl[:2]) + classdict[identify(klass[:2])] = klass[1:] + for enum in enums: + enumdict[enum[0]] = enum[1] + return name, eventdict, classdict, enumdict + +def combinesuite(suite): + """Combines suite dictionaries to seperate event, class, enumeration dictionaries + """ + + suitelist = [] + eventDict ={} + classDict ={} + enumDict ={} + for value in suite.values(): + for key in value[0].keys(): + val = value[0][key] + eventDict[key] = val + for key in value[1].keys(): + val = value[1][key] + if key in classDict.keys(): + nval = classDict[key][2] + val[2] = val[2] + nval + classDict[key] = val + for key in value[2].keys(): + val = value[2][key] + enumDict[key] = val + return eventDict, classDict, enumDict + + +illegal_ids = [ "for", "in", "from", "and", "or", "not", "print", "class", "return", + "def", "name", 'data' ] + +def identify(str): + """Turn any string into an identifier: + - replace space by _ + - remove ',' and '-' + capitalise + """ + if not str[0]: + if str[1] == 'c@#!': + return "Every" + else: + return 'Any' + rv = string.replace(str[0], ' ', '_') + rv = string.replace(rv, '-', '') + rv = string.replace(rv, ',', '') + rv = string.capitalize(rv) + return rv + + +def openaete(app): + """open and read the aete of the target application""" + arguments['----'] = LANG + _aete = AETE(app) + _reply, _arguments, _attributes = _aete.send(kASAppleScriptSuite, kGetAETE, arguments, attributes) + if _arguments.has_key('errn'): + raise baetools.Error, baetools.decodeerror(_arguments) + return _arguments + +def openaeut(): + """Open and read a aeut file. + XXXXX This has been temporarily hard coded until a Python aeut is written XXXX""" + + fullname = dialect + rf = OpenRFPerm(fullname, 0, 1) + try: + UseResFile(rf) + resources = [] + for i in range(Count1Resources('aeut')): + res = Get1IndResource('aeut', 1+i) + resources.append(res) + for res in resources: + data = res.data + data = decode(data)[4] + finally: + CloseResFile(rf) + return data + +def dialect(): + """find the correct Dialect file""" + + dialect = lang[LANG] + " Dialect" + try: + ##System 8 + vRefNum, dirID = macfs.FindFolder(kOnSystemDisk, kScriptingAdditionsFolderType, 0) + fss = macfs.FSSpec((vRefNum, dirID, '')) + fss = fss.as_pathname() + except macfs.error: + ##Sytem 7 + vRefNum, dirID = macfs.FindFolder(kOnSystemDisk, kExtensionFolderType, 0) + fss = macfs.FSSpec((vRefNum, dirID, '')) + fss = fss.as_pathname() + fss = macpath.join(fss, "Scripting Additions") + fss = macpath.join(fss, "Dialect") + fss = macpath.join(fss, dialect) + return fss + + +#def openosax(): +# """Open and read the aetes of osaxen in the scripting additions folder""" +# +# # System 7.x +# aete = [] +# vRefNum, dirID = macfs.FindFolder(kOnSystemDisk, kExtensionFolderType, 0) +# fss = macfs.FSSpec((vRefNum, dirID, '')) +# fss = fss.as_pathname() +# osax = macpath.join(fss, "Scripting Additions") +# for file in os.listdir(osax): +# fullname = macpath.join(osax, file) +# print fullname +# rf = OpenRFPerm(fullname, 0, 1) +# try: +# UseResFile(rf) +# resources = [] +# for i in range(Count1Resources('aete')): +# res = Get1IndResource('aete', 1+i) +# resources.append(res) +# for res in resources: +# data = res.data +# data = decode(data)[4] +# finally: +# CloseResFile(rf) +# aete.append(data) +# print data + + +#The following should be replaced by direct access to a python 'aeut' + +def _launch(appfile): + """Open a file thru the finder. Specify file by name or fsspec""" + +# from PythonScript import PyScript + import baetypes + _finder = AETE('MACS') + parameters ={} + parameters['----'] = eval("baetypes.ObjectSpecifier('%s', '%s', %s)" % ('appf', 'ID ', `appfile`)) + _reply, _arguments, _attributes = _finder.send( 'aevt', 'odoc', parameters , attributes = {}) + if _arguments.has_key('errn'): + raise baetools.Error, baetools.decodeerror(_arguments) + # XXXX Optionally decode result + if _arguments.has_key('----'): + return _arguments['----'] + + + +if __name__ == '__main__': +# import profile +# profile.run('Getaete(app)', 'Getaeteprof') + Getaete(app) +# openosax() +# openaete('ascr') +# sys.exit(1) |