blob: 68eb825f60140b5f0fa1e9b73f402572836f1864 [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
32# Special code to unpack an AppleEvent (which is *not* a disguised record!)
Jack Jansen40775ba1995-07-17 11:42:23 +000033# Note by Jack: No??!? If I read the docs correctly it *is*....
Guido van Rossum31559231995-02-05 16:59:27 +000034
Guido van Rossum17448e21995-01-30 11:53:55 +000035aekeywords = [
36 'tran',
37 'rtid',
38 'evcl',
39 'evid',
40 'addr',
41 'optk',
42 'timo',
43 'inte', # this attribute is read only - will be set in AESend
44 'esrc', # this attribute is read only
45 'miss', # this attribute is read only
46 'from' # new in 1.0.1
47]
48
49def missed(ae):
50 try:
51 desc = ae.AEGetAttributeDesc('miss', 'keyw')
52 except AE.Error, msg:
53 return None
54 return desc.data
55
56def unpackevent(ae):
57 parameters = {}
58 while 1:
59 key = missed(ae)
60 if not key: break
61 parameters[key] = unpack(ae.AEGetParamDesc(key, '****'))
62 attributes = {}
63 for key in aekeywords:
64 try:
65 desc = ae.AEGetAttributeDesc(key, '****')
66 except (AE.Error, MacOS.Error), msg:
67 if msg[0] != -1701:
68 raise sys.exc_type, sys.exc_value
69 continue
70 attributes[key] = unpack(desc)
71 return parameters, attributes
72
73def packevent(ae, parameters = {}, attributes = {}):
74 for key, value in parameters.items():
75 ae.AEPutParamDesc(key, pack(value))
76 for key, value in attributes.items():
77 ae.AEPutAttributeDesc(key, pack(value))
78
Jack Jansen40775ba1995-07-17 11:42:23 +000079#
80# Support routine for automatically generated Suite interfaces
Jack Jansen84264771995-10-03 14:35:58 +000081# These routines are also useable for the reverse function.
Jack Jansen40775ba1995-07-17 11:42:23 +000082#
83def keysubst(arguments, keydict):
84 """Replace long name keys by their 4-char counterparts, and check"""
85 ok = keydict.values()
86 for k in arguments.keys():
87 if keydict.has_key(k):
88 v = arguments[k]
89 del arguments[k]
90 arguments[keydict[k]] = v
91 elif k != '----' and k not in ok:
92 raise TypeError, 'Unknown keyword argument: %s'%k
93
94def enumsubst(arguments, key, edict):
95 """Substitute a single enum keyword argument, if it occurs"""
96 if not arguments.has_key(key):
97 return
98 v = arguments[key]
99 ok = edict.values()
100 if edict.has_key(v):
101 arguments[key] = edict[v]
102 elif not v in ok:
103 raise TypeError, 'Unknown enumerator: %s'%v
104
105def decodeerror(arguments):
106 """Create the 'best' argument for a raise MacOS.Error"""
107 errn = arguments['errn']
108 errarg = (errn, MacOS.GetErrorString(errn))
109 if arguments.has_key('errs'):
110 errarg = errarg + (arguments['errs'],)
111 if arguments.has_key('erob'):
112 errarg = errarg + (arguments['erob'],)
113 return errarg
Guido van Rossum31559231995-02-05 16:59:27 +0000114
Jack Jansen40775ba1995-07-17 11:42:23 +0000115class TalkTo:
116 """An AE connection to an application"""
117
118 def __init__(self, signature):
119 """Create a communication channel with a particular application.
120
121 Addressing the application is done by specifying either a
122 4-byte signature, an AEDesc or an object that will __aepack__
123 to an AEDesc.
124 """
125 if type(signature) == AEDescType:
126 self.target = signature
127 elif type(signature) == InstanceType and hasattr(signature, '__aepack__'):
128 self.target = signature.__aepack__()
Jack Jansen7874b5d1995-07-29 15:31:10 +0000129 elif type(signature) == StringType and len(signature) == 4:
Jack Jansen40775ba1995-07-17 11:42:23 +0000130 self.target = AE.AECreateDesc(AppleEvents.typeApplSignature, signature)
131 else:
132 raise TypeError, "signature should be 4-char string or AEDesc"
133 self.send_flags = AppleEvents.kAEWaitReply
134 self.send_priority = AppleEvents.kAENormalPriority
135 self.send_timeout = AppleEvents.kAEDefaultTimeout
136
137 def newevent(self, code, subcode, parameters = {}, attributes = {}):
138 """Create a complete structure for an apple event"""
139
140 event = AE.AECreateAppleEvent(code, subcode, self.target,
141 AppleEvents.kAutoGenerateReturnID, AppleEvents.kAnyTransactionID)
142 packevent(event, parameters, attributes)
143 return event
144
145 def sendevent(self, event):
146 """Send a pre-created appleevent, await the reply and unpack it"""
147
148 reply = event.AESend(self.send_flags, self.send_priority,
149 self.send_timeout)
150 parameters, attributes = unpackevent(reply)
151 return reply, parameters, attributes
152
153 def send(self, code, subcode, parameters = {}, attributes = {}):
154 """Send an appleevent given code/subcode/pars/attrs and unpack the reply"""
155 return self.sendevent(self.newevent(code, subcode, parameters, attributes))
156
157 def activate(self):
158 """Send 'activate' command"""
159 self.send('misc', 'actv')
160
161
Guido van Rossum31559231995-02-05 16:59:27 +0000162# Test program
Jack Jansen40775ba1995-07-17 11:42:23 +0000163# XXXX Should test more, really...
Guido van Rossum31559231995-02-05 16:59:27 +0000164
Guido van Rossum17448e21995-01-30 11:53:55 +0000165def test():
166 target = AE.AECreateDesc('sign', 'KAHL')
167 ae = AE.AECreateAppleEvent('aevt', 'oapp', target, -1, 0)
168 print unpackevent(ae)
Guido van Rossum31559231995-02-05 16:59:27 +0000169 raw_input(":")
170 ae = AE.AECreateAppleEvent('core', 'getd', target, -1, 0)
171 obj = Character(2, Word(1, Document(1)))
172 print obj
173 print repr(obj)
174 packevent(ae, {'----': obj})
175 params, attrs = unpackevent(ae)
176 print params['----']
177 raw_input(":")
Guido van Rossum17448e21995-01-30 11:53:55 +0000178
179if __name__ == '__main__':
180 test()