blob: 41b7f2497084680d500b7429f158fa967c083608 [file] [log] [blame]
Guido van Rossum31559231995-02-05 16:59:27 +00001"""Tools for use in AppleEvent clients and servers.
2
3pack(x) converts a Python object to an AEDesc object
4unpack(desc) does the reverse
5
6packevent(event, parameters, attributes) sets params and attrs in an AEAppleEvent record
7unpackevent(event) returns the parameters and attributes from an AEAppleEvent record
8
9Plus... Lots of classes and routines that help representing AE objects,
10ranges, conditionals, logicals, etc., so you can write, e.g.:
11
12 x = Character(1, Document("foobar"))
13
14and pack(x) will create an AE object reference equivalent to AppleScript's
15
16 character 1 of document "foobar"
17
Jack Jansen40775ba1995-07-17 11:42:23 +000018Some of the stuff that appears to be exported from this module comes from other
19files: the pack stuff from aepack, the objects from aetypes.
20
Guido van Rossum31559231995-02-05 16:59:27 +000021"""
22
23
Guido van Rossum31559231995-02-05 16:59:27 +000024from types import *
Guido van Rossum17448e21995-01-30 11:53:55 +000025import AE
Jack Jansen40775ba1995-07-17 11:42:23 +000026import AppleEvents
Guido van Rossum17448e21995-01-30 11:53:55 +000027import MacOS
Guido van Rossum17448e21995-01-30 11:53:55 +000028
Jack Jansen40775ba1995-07-17 11:42:23 +000029from aetypes import *
30from aepack import pack, unpack, coerce, AEDescType
Guido van Rossum31559231995-02-05 16:59:27 +000031
Jack Jansenc46f56e1996-09-20 15:28:28 +000032Error = 'aetools.Error'
33
Guido van Rossum31559231995-02-05 16:59:27 +000034# Special code to unpack an AppleEvent (which is *not* a disguised record!)
Jack Jansen40775ba1995-07-17 11:42:23 +000035# Note by Jack: No??!? If I read the docs correctly it *is*....
Guido van Rossum31559231995-02-05 16:59:27 +000036
Guido van Rossum17448e21995-01-30 11:53:55 +000037aekeywords = [
38 'tran',
39 'rtid',
40 'evcl',
41 'evid',
42 'addr',
43 'optk',
44 'timo',
45 'inte', # this attribute is read only - will be set in AESend
46 'esrc', # this attribute is read only
47 'miss', # this attribute is read only
48 'from' # new in 1.0.1
49]
50
51def missed(ae):
52 try:
53 desc = ae.AEGetAttributeDesc('miss', 'keyw')
54 except AE.Error, msg:
55 return None
56 return desc.data
57
58def unpackevent(ae):
59 parameters = {}
60 while 1:
61 key = missed(ae)
62 if not key: break
63 parameters[key] = unpack(ae.AEGetParamDesc(key, '****'))
64 attributes = {}
65 for key in aekeywords:
66 try:
67 desc = ae.AEGetAttributeDesc(key, '****')
68 except (AE.Error, MacOS.Error), msg:
69 if msg[0] != -1701:
70 raise sys.exc_type, sys.exc_value
71 continue
72 attributes[key] = unpack(desc)
73 return parameters, attributes
74
75def packevent(ae, parameters = {}, attributes = {}):
76 for key, value in parameters.items():
77 ae.AEPutParamDesc(key, pack(value))
78 for key, value in attributes.items():
79 ae.AEPutAttributeDesc(key, pack(value))
80
Jack Jansen40775ba1995-07-17 11:42:23 +000081#
82# Support routine for automatically generated Suite interfaces
Jack Jansen84264771995-10-03 14:35:58 +000083# These routines are also useable for the reverse function.
Jack Jansen40775ba1995-07-17 11:42:23 +000084#
85def keysubst(arguments, keydict):
86 """Replace long name keys by their 4-char counterparts, and check"""
87 ok = keydict.values()
88 for k in arguments.keys():
89 if keydict.has_key(k):
90 v = arguments[k]
91 del arguments[k]
92 arguments[keydict[k]] = v
93 elif k != '----' and k not in ok:
94 raise TypeError, 'Unknown keyword argument: %s'%k
95
96def enumsubst(arguments, key, edict):
97 """Substitute a single enum keyword argument, if it occurs"""
98 if not arguments.has_key(key):
99 return
100 v = arguments[key]
101 ok = edict.values()
102 if edict.has_key(v):
103 arguments[key] = edict[v]
104 elif not v in ok:
105 raise TypeError, 'Unknown enumerator: %s'%v
106
107def decodeerror(arguments):
108 """Create the 'best' argument for a raise MacOS.Error"""
109 errn = arguments['errn']
Jack Jansenc46f56e1996-09-20 15:28:28 +0000110 errarg = (errn, )
Jack Jansen40775ba1995-07-17 11:42:23 +0000111 if arguments.has_key('errs'):
112 errarg = errarg + (arguments['errs'],)
113 if arguments.has_key('erob'):
114 errarg = errarg + (arguments['erob'],)
Jack Jansenc46f56e1996-09-20 15:28:28 +0000115 if len(errarg) == 1:
116 errarg = errarg + ('Server returned error code %d'%errn, )
Jack Jansen40775ba1995-07-17 11:42:23 +0000117 return errarg
Guido van Rossum31559231995-02-05 16:59:27 +0000118
Jack Jansen40775ba1995-07-17 11:42:23 +0000119class TalkTo:
120 """An AE connection to an application"""
121
Jack Jansenc46f56e1996-09-20 15:28:28 +0000122 def __init__(self, signature, start=0):
Jack Jansen40775ba1995-07-17 11:42:23 +0000123 """Create a communication channel with a particular application.
124
125 Addressing the application is done by specifying either a
126 4-byte signature, an AEDesc or an object that will __aepack__
127 to an AEDesc.
128 """
Jack Jansenc46f56e1996-09-20 15:28:28 +0000129 self.target_signature = None
Jack Jansen40775ba1995-07-17 11:42:23 +0000130 if type(signature) == AEDescType:
131 self.target = signature
132 elif type(signature) == InstanceType and hasattr(signature, '__aepack__'):
133 self.target = signature.__aepack__()
Jack Jansen7874b5d1995-07-29 15:31:10 +0000134 elif type(signature) == StringType and len(signature) == 4:
Jack Jansen40775ba1995-07-17 11:42:23 +0000135 self.target = AE.AECreateDesc(AppleEvents.typeApplSignature, signature)
Jack Jansenc46f56e1996-09-20 15:28:28 +0000136 self.target_signature = signature
Jack Jansen40775ba1995-07-17 11:42:23 +0000137 else:
138 raise TypeError, "signature should be 4-char string or AEDesc"
139 self.send_flags = AppleEvents.kAEWaitReply
140 self.send_priority = AppleEvents.kAENormalPriority
141 self.send_timeout = AppleEvents.kAEDefaultTimeout
Jack Jansenc46f56e1996-09-20 15:28:28 +0000142 if start:
143 self.start()
144
145 def start(self):
146 """Start the application, if it is not running yet"""
147 import findertools
148 import macfs
149
150 fss = macfs.FindApplication(self.target_signature)
151 findertools.launch(fss)
152
Jack Jansen40775ba1995-07-17 11:42:23 +0000153 def newevent(self, code, subcode, parameters = {}, attributes = {}):
154 """Create a complete structure for an apple event"""
155
156 event = AE.AECreateAppleEvent(code, subcode, self.target,
157 AppleEvents.kAutoGenerateReturnID, AppleEvents.kAnyTransactionID)
158 packevent(event, parameters, attributes)
159 return event
160
161 def sendevent(self, event):
162 """Send a pre-created appleevent, await the reply and unpack it"""
163
164 reply = event.AESend(self.send_flags, self.send_priority,
165 self.send_timeout)
166 parameters, attributes = unpackevent(reply)
167 return reply, parameters, attributes
168
169 def send(self, code, subcode, parameters = {}, attributes = {}):
170 """Send an appleevent given code/subcode/pars/attrs and unpack the reply"""
171 return self.sendevent(self.newevent(code, subcode, parameters, attributes))
172
Jack Jansen7e156a71996-01-29 15:45:09 +0000173 #
174 # The following events are somehow "standard" and don't seem to appear in any
175 # suite...
176 #
Jack Jansen40775ba1995-07-17 11:42:23 +0000177 def activate(self):
178 """Send 'activate' command"""
179 self.send('misc', 'actv')
Jack Jansen7e156a71996-01-29 15:45:09 +0000180
181 def get(self, _object, _attributes={}):
182 """get: get data from an object
183 Required argument: the object
184 Keyword argument _attributes: AppleEvent attribute dictionary
185 Returns: the data
186 """
187 _code = 'core'
188 _subcode = 'getd'
189
190 _arguments = {'----':_object}
191
192
193 _reply, _arguments, _attributes = self.send(_code, _subcode,
194 _arguments, _attributes)
195 if _arguments.has_key('errn'):
Jack Jansenc46f56e1996-09-20 15:28:28 +0000196 raise Error, decodeerror(_arguments)
Jack Jansen7e156a71996-01-29 15:45:09 +0000197
198 if _arguments.has_key('----'):
199 return _arguments['----']
Jack Jansen40775ba1995-07-17 11:42:23 +0000200
201
Guido van Rossum31559231995-02-05 16:59:27 +0000202# Test program
Jack Jansen40775ba1995-07-17 11:42:23 +0000203# XXXX Should test more, really...
Guido van Rossum31559231995-02-05 16:59:27 +0000204
Guido van Rossum17448e21995-01-30 11:53:55 +0000205def test():
206 target = AE.AECreateDesc('sign', 'KAHL')
207 ae = AE.AECreateAppleEvent('aevt', 'oapp', target, -1, 0)
208 print unpackevent(ae)
Guido van Rossum31559231995-02-05 16:59:27 +0000209 raw_input(":")
210 ae = AE.AECreateAppleEvent('core', 'getd', target, -1, 0)
211 obj = Character(2, Word(1, Document(1)))
212 print obj
213 print repr(obj)
214 packevent(ae, {'----': obj})
215 params, attrs = unpackevent(ae)
216 print params['----']
217 raw_input(":")
Guido van Rossum17448e21995-01-30 11:53:55 +0000218
219if __name__ == '__main__':
220 test()