Jack Jansen | 7cc5735 | 1998-08-18 14:54:11 +0000 | [diff] [blame^] | 1 | """ |
| 2 | Python script a module to comunicate with apple events |
| 3 | |
| 4 | v 0.1a2 |
| 5 | v.0.2 16 april 1998 |
| 6 | |
| 7 | |
| 8 | """ |
| 9 | import sys |
| 10 | import getaete |
| 11 | import baetools |
| 12 | import baetypes |
| 13 | import AE |
| 14 | import AppleEvents |
| 15 | import macfs |
| 16 | from types import * |
| 17 | #from aetypes import InstanceType |
| 18 | from aepack import AEDescType |
| 19 | |
| 20 | ordinal = { |
| 21 | 'every': 'all ', |
| 22 | 'first' : 'firs', |
| 23 | 'last' : 'last', |
| 24 | 'any' : 'any ', |
| 25 | 'middle' : 'midd'} |
| 26 | |
| 27 | |
| 28 | Error = 'PythonScript.Error' |
| 29 | |
| 30 | |
| 31 | class PsEvents: |
| 32 | pass |
| 33 | |
| 34 | |
| 35 | class PsClasses: |
| 36 | |
| 37 | |
| 38 | def __getattr__(self, name): |
| 39 | try: |
| 40 | return DCItem(name, self) |
| 41 | except: |
| 42 | pass |
| 43 | |
| 44 | def __repr__(self): |
| 45 | if self.form != 'prop': |
| 46 | t = type(self.seld) |
| 47 | if t == StringType: |
| 48 | self.form = 'name' |
| 49 | elif baetypes.IsRange(self.seld): |
| 50 | self.form = 'rang' |
| 51 | elif baetypes.IsComparison(self.seld) or baetypes.IsLogical(self.seld): |
| 52 | self.form = 'test' |
| 53 | elif t == TupleType: |
| 54 | # Breakout: specify both form and seld in a tuple |
| 55 | # (if you want ID or rele or somesuch) |
| 56 | self.form, self.seld = self.seld |
| 57 | elif t == IntType: |
| 58 | self.form = 'indx' |
| 59 | else: |
| 60 | pass |
| 61 | |
| 62 | if self.seld in ordinal.keys(): |
| 63 | self.seld = baetypes.Ordinal(ordinal[self.seld]) |
| 64 | self.form = 'indx' |
| 65 | |
| 66 | s = "baetypes.ObjectSpecifier(%s, %s, %s" % (`self.want`, `self.form`, `self.seld`) |
| 67 | if `self.fr`: |
| 68 | s = s + ", %s)" % `self.fr` |
| 69 | else: |
| 70 | s = s + ")" |
| 71 | return s |
| 72 | |
| 73 | def __str__(self): |
| 74 | return self.want |
| 75 | |
| 76 | |
| 77 | def template(self, seld=None, fr=None): |
| 78 | self.seld = seld |
| 79 | self.fr = fr |
| 80 | |
| 81 | def template1(self, which, fr=None): |
| 82 | self.want = 'prop' |
| 83 | self.form = 'prop' |
| 84 | self.fr = fr |
| 85 | |
| 86 | class DCItem: |
| 87 | def __init__(self, comp, fr): |
| 88 | self.compclass = comp |
| 89 | self.fr = fr |
| 90 | |
| 91 | def __call__(self, which=None): |
| 92 | if which: |
| 93 | self.compclass = eval('PsClass.%s' % self.compclass) |
| 94 | else: |
| 95 | try: |
| 96 | self.compclass = eval('PsProperties.%s' % self.compclass) |
| 97 | except AttributeError: |
| 98 | self.compclass = eval('PsClass.%s' % self.compclass) |
| 99 | return self.compclass(which, self.fr) |
| 100 | |
| 101 | class PsClass: |
| 102 | pass |
| 103 | |
| 104 | class PsProperties: |
| 105 | pass |
| 106 | |
| 107 | |
| 108 | class PsEnumerations: |
| 109 | pass |
| 110 | |
| 111 | |
| 112 | def PsScript(sig=None, Timeout=0, Ignoring=0): |
| 113 | elements = {} |
| 114 | if sig: |
| 115 | target, sig = Signature(sig) |
| 116 | pyscript = getaete.Getaete(sig) |
| 117 | else: |
| 118 | target, sig = Signature('Pyth') |
| 119 | pyscript = getaete.Getaete() |
| 120 | setattr(PyScript, 'timeout', Timeout) |
| 121 | setattr(PyScript, 'ignoring', Ignoring) |
| 122 | setattr(PyScript, 'target', target) |
| 123 | for key, value in pyscript[0].items(): |
| 124 | setattr(PsEvents, key, value) |
| 125 | for key, value in pyscript[1].items(): |
| 126 | CreateClass(key, 'PsClasses', value) |
| 127 | for val in value[2]: |
| 128 | CreateProperty(val[0], 'PsClasses', `val[1]`) |
| 129 | |
| 130 | if value[3]: |
| 131 | for val in value[3]: |
| 132 | if val[0] not in elements.keys(): |
| 133 | elements[val[0]] = val[1] |
| 134 | elif len(val[1]) > len(elements[val[0]]): |
| 135 | elements[val[0]] = val[1] |
| 136 | |
| 137 | for key, value in pyscript[2].items(): |
| 138 | for val in value: |
| 139 | setattr(PsEnumerations, val[0], val[1]) |
| 140 | |
| 141 | def CreateClass(newClassName, superClassName, value): |
| 142 | parentDict = PsClass.__dict__ |
| 143 | exec "class %s(%s): pass" % (newClassName, superClassName) in \ |
| 144 | globals(), parentDict |
| 145 | newClassObj = parentDict[newClassName] |
| 146 | newClassObj.__init__ = template |
| 147 | exec "setattr(newClassObj, 'want', %s)" % `value[0]` |
| 148 | if value[2] and value[2][0][0] == 'every': |
| 149 | exec "setattr(newClassObj, 'plur', 1)" |
| 150 | |
| 151 | def CreateProperty(newClassName, superClassName, value): |
| 152 | parentDict = PsProperties.__dict__ |
| 153 | exec "class %s(%s): pass" % (newClassName, superClassName) in \ |
| 154 | globals(), parentDict |
| 155 | newClassObj = parentDict[newClassName] |
| 156 | if newClassName == 'Every': |
| 157 | value = "baetypes.mkOrdinal('every')" |
| 158 | newClassObj.__init__ = template1 |
| 159 | exec "setattr(newClassObj, 'seld', %s)" % value |
| 160 | |
| 161 | def Signature(signature): |
| 162 | if type(signature) == AEDescType: |
| 163 | target = signature |
| 164 | elif type(signature) == InstanceType and hasattr(signature, '__aepack__'): |
| 165 | target = signature.__aepack__() |
| 166 | elif type(signature) == StringType: |
| 167 | if len(signature) == 4: |
| 168 | target = AE.AECreateDesc(AppleEvents.typeApplSignature, signature) |
| 169 | target_signature = signature |
| 170 | else: |
| 171 | #This should ready be made persistant, so PythonScript 'remembered' where applications were |
| 172 | fss, ok = macfs.PromptGetFile('Find the aplication %s' % signature, 'APPL') |
| 173 | if ok: |
| 174 | target_signature = fss.GetCreatorType()[0] |
| 175 | target = AE.AECreateDesc(AppleEvents.typeApplSignature, target_signature) |
| 176 | else: |
| 177 | raise TypeError, "signature should be 4-char string or AEDesc" |
| 178 | return target, target_signature |
| 179 | |
| 180 | |
| 181 | |
| 182 | |
| 183 | class PyScript(PsEvents): |
| 184 | def __init__(self, name, obj=None, **args): |
| 185 | desc, code, subcode, rply, message, keywds = name |
| 186 | # print 'code', code |
| 187 | # print 'subcode', subcode |
| 188 | # print 'rply', rply |
| 189 | # print 'message', message |
| 190 | # print 'keywds', keywds |
| 191 | # print 'name', name |
| 192 | # print 'obj', obj |
| 193 | # print 'args', args |
| 194 | self.code = code |
| 195 | self.subcode = subcode |
| 196 | self.attributes ={} |
| 197 | self.arguments = {} |
| 198 | if keywds: |
| 199 | self.arguments = self.keyargs(keywds, args) |
| 200 | self.arguments['----'] = self.keyfms(message[0], obj) |
| 201 | |
| 202 | ##XXXX Eudora needs this XXXX## |
| 203 | if self.arguments['----'] == None: |
| 204 | del self.arguments['----'] |
| 205 | # print 'arguments', self.arguments |
| 206 | if self.ignoring or rply[0] == 'null': |
| 207 | self.send_flags = AppleEvents.kAENoReply |
| 208 | else: |
| 209 | self.send_flags = AppleEvents.kAEWaitReply |
| 210 | self.send_priority = AppleEvents.kAENormalPriority |
| 211 | if self.timeout: |
| 212 | self.send_timeout = self.timeout |
| 213 | else: |
| 214 | self.send_timeout = AppleEvents.kAEDefaultTimeout |
| 215 | |
| 216 | |
| 217 | def keyargs(self, ats, args): |
| 218 | # print 'keyargs', ats, args |
| 219 | output = {} |
| 220 | for arg in args.keys(): |
| 221 | for at in ats: |
| 222 | if at[0] == arg: |
| 223 | output[at[1]] = self.keyfms(at[2][0], args[arg]) |
| 224 | return output |
| 225 | |
| 226 | def keyfms(self, key, value): |
| 227 | # print 'keyfms', 'key', key, `value` |
| 228 | if key == 'obj ' or key == 'insl': |
| 229 | return eval(`value`) |
| 230 | elif key == 'TEXT': |
| 231 | return value |
| 232 | elif key == 'null': |
| 233 | return |
| 234 | elif key == 'bool': |
| 235 | return baetypes.mkboolean(value) |
| 236 | elif key == 'type': |
| 237 | try: |
| 238 | val = eval('PsClass.%s()' % value) |
| 239 | return baetypes.mktype(str(val)) |
| 240 | except: |
| 241 | return baetypes.mktype(value) |
| 242 | else: |
| 243 | print "I don't know what to put here -- script.keyargs" |
| 244 | print key, `value` |
| 245 | sys.exit[1] |
| 246 | |
| 247 | def newevent(self, code, subcode, parameters = {}, attributes = {}): |
| 248 | """Create a complete structure for an apple event""" |
| 249 | # print code, subcode, parameters, attributes |
| 250 | event = AE.AECreateAppleEvent(code, subcode, self.target, |
| 251 | AppleEvents.kAutoGenerateReturnID, AppleEvents.kAnyTransactionID) |
| 252 | baetools.packevent(event, parameters, attributes) |
| 253 | return event |
| 254 | |
| 255 | def sendevent(self, event): |
| 256 | """Send a pre-created appleevent, await the reply and unpack it""" |
| 257 | |
| 258 | reply = event.AESend(self.send_flags, self.send_priority, |
| 259 | self.send_timeout) |
| 260 | parameters, attributes = baetools.unpackevent(reply) |
| 261 | return reply, parameters, attributes |
| 262 | |
| 263 | def send(self, code, subcode, parameters = {}, attributes = {}): |
| 264 | """Send an appleevent given code/subcode/pars/attrs and unpack the reply""" |
| 265 | # print code, subcode, parameters, attributes |
| 266 | return self.sendevent(self.newevent(code, subcode, parameters, attributes)) |
| 267 | |
| 268 | def __str__(self): |
| 269 | _reply, _arguments, _attributes = self.send(self.code, self.subcode, self.arguments, self.attributes) |
| 270 | |
| 271 | if _arguments.has_key('errn'): |
| 272 | raise baetools.Error, baetools.decodeerror(_arguments) |
| 273 | # XXXX Optionally decode result |
| 274 | if _arguments.has_key('----'): |
| 275 | return str(_arguments['----']) |
| 276 | else: |
| 277 | return |
| 278 | |
| 279 | |
| 280 | |
| 281 | def test(): |
| 282 | Simp = 'Hermit:Applications:SimpleText' |
| 283 | PsScript('MACS', Timeout=60*60*3) |
| 284 | # PsScript('CSOm', Timeout=60*60*3) |
| 285 | # PsScript('', Timeout=60*60*3) |
| 286 | # PyScript('macsoup') |
| 287 | ev = PsEvents |
| 288 | ps = PsClass |
| 289 | # print PsProperties.__dict__ |
| 290 | # y = script(ev.Open, File('Hermit:Desktop Folder:Lincolnshire Imp'), using=Application_file(Simp)) |
| 291 | # print baetypes.NProperty('prop', 'prop', 'pnam', baetypes.ObjectSpecifier('cdis', 'indx', 1, None)) |
| 292 | # y = PyScript(ev.Get, Disk("Hermit").Folder(7).File(1).Name()) |
| 293 | # y = PyScript(ev.Get, Disk("Hermit").Size(), As='Integer') |
| 294 | # y = PyScript(ev.Get, ps.Desktopobject(1).Startup_disk()) |
| 295 | # y = PyScript(ev.Get, Mailbox(1).File(), as='TEXT') |
| 296 | # print 'y', y, type(y) |
| 297 | |
| 298 | if __name__ == '__main__': |
| 299 | test() |
| 300 | # sys.exit(1) |
| 301 | |