blob: 745bce78abbf25ab7e51f44970396d6277db8ded [file] [log] [blame]
Guido van Rossum17448e21995-01-30 11:53:55 +00001import struct
2import types
3import AE
4import MacOS
5import StringIO
6
7AEDescType = type(AE.AECreateDesc('TEXT', ''))
8
9def pack(x):
10 if x == None:
11 return AE.AECreateDesc('null', '')
12 t = type(x)
13 if t == AEDescType:
14 return x
15 if t == types.IntType:
16 return AE.AECreateDesc('long', struct.pack('l', x))
17 if t == types.FloatType:
18 return AE.AECreateDesc('exte', struct.pack('d', x)[2:])
19 if t == types.StringType:
20 return AE.AECreateDesc('TEXT', x)
21 if t == types.ListType:
22 list = AE.AECreateList('', 0)
23 for item in x:
24 list.AEPutDesc(0, pack(item))
25 return list
26 if t == types.TupleType:
27 t, d = x
28 return AE.AECreateDesc(t, d)
29 if t == types.DictionaryType:
30 record = AE.AECreateList('', 1)
31 for key, value in x.items():
32 record.AEPutKeyDesc(key, pack(value))
33 if t == types.InstanceType and hasattr(x, '__aepack__'):
34 return x.__aepack__()
35 return AE.AECreateDesc('TEXT', repr(x)) # Copout
36
37def unpack(desc):
38 t = desc.type
39 if t == 'TEXT':
40 return desc.data
41 if t == 'fals':
42 return 0
43 if t == 'true':
44 return 1
45 if t == 'long':
46 return struct.unpack('l', desc.data)[0]
47 if t == 'shor':
48 return struct.unpack('h', desc.data)[0]
49 if t == 'sing':
50 return struct.unpack('f', desc.data)[0]
51 if t == 'exte':
52 data = desc.data
53 return struct.unpack('d', data[:2] + data)[0]
54 if t in ('doub', 'comp', 'magn'):
55 return unpack(desc.AECoerceDesc('exte'))
56 if t == 'enum':
57 return ('enum', desc.data)
58 if t == 'null':
59 return None
60 if t == 'list':
61 l = []
62 for i in range(desc.AECountItems()):
63 keyword, item = desc.AEGetNthDesc(i+1, '****')
64 l.append(unpack(item))
65 return l
66 if t == 'reco':
67 d = {}
68 for i in range(desc.AECountItems()):
69 keyword, item = desc.AEGetNthDesc(i+1, '****')
70 d[keyword] = unpack(item)
71 return d
72 if t == 'obj ':
73 return unpackobject(desc.data)
74 return desc.type, desc.data # Copout
75
76class Object:
77 def __init__(self, dict = {}):
78 self.dict = dict
79 for key, value in dict.items():
80 self.dict[key] = value
81 def __repr__(self):
82 return "Object(%s)" % `self.dict`
83 def __str__(self):
84 want = self.dict['want']
85 form = self.dict['form']
86 seld = self.dict['seld']
87 s = "%s %s %s" % (nicewant(want), niceform(form), niceseld(seld))
88 fr = self.dict['from']
89 if fr:
90 s = s + " of " + str(fr)
91 return s
92 def __aepack__(self):
93 f = StringIO.StringIO()
94 putlong(f, len(self.dict))
95 putlong(f, 0)
96 for key, value in self.dict.items():
97 putcode(f, key)
98 desc = pack(value)
99 putcode(f, desc.type)
100 data = desc.data
101 putlong(f, len(data))
102 f.write(data)
103 return AE.AECreateDesc('obj ', f.getvalue())
104
105def nicewant(want):
106 if type(want) == types.TupleType and len(want) == 2:
107 return reallynicewant(want)
108 else:
109 return `want`
110
111def reallynicewant((t, w)):
112 if t != 'type': return `t, w`
113 # These should be taken from the "elements" of the 'aete' resource
114 if w == 'cins': return 'insertion point'
115 if w == 'cha ': return 'character'
116 if w == 'word': return 'word'
117 if w == 'para': return 'paragraph'
118 if w == 'ccel': return 'cell'
119 if w == 'ccol': return 'column'
120 if w == 'crow': return 'row'
121 if w == 'crng': return 'range'
122 if w == 'wind': return 'window'
123 if w == 'docu': return 'document'
124 return `w`
125
126def niceform(form):
127 if type(form) == types.TupleType and len(form) == 2:
128 return reallyniceform(form)
129 else:
130 return `form`
131
132def reallyniceform((t, f)):
133 if t <> 'enum': return `t, f`
134 if f == 'indx': return ''
135 if f == 'name': return ''
136 if f == 'rele': return ''
137 return `f`
138
139def niceseld(seld):
140 if type(seld) == types.TupleType and len(seld) == 2:
141 return reallyniceseld(seld)
142 else:
143 return `seld`
144
145def reallyniceseld((t, s)):
146 if t == 'long': return `s`
147 if t == 'TEXT': return `s`
148 if t == 'enum':
149 if s == 'next': return 'after'
150 if s == 'prev': return 'before'
151 return `t, s`
152
153def unpackobject(data):
154 f = StringIO.StringIO(data)
155 nkey = getlong(f)
156 dumm = getlong(f)
157 dict = {}
158 for i in range(nkey):
159 keyw = getcode(f)
160 type = getcode(f)
161 size = getlong(f)
162 if size:
163 data = f.read(size)
164 else:
165 data = ''
166 desc = AE.AECreateDesc(type, data)
167 dict[keyw] = unpack(desc)
168 return Object(dict)
169
170
171# --- get various data types from a "file"
172
173def getword(f, *args):
174 getalgn(f)
175 s = f.read(2)
176 if len(s) < 2:
177 raise EOFError, 'in getword' + str(args)
178 return (ord(s[0])<<8) | ord(s[1])
179
180def getlong(f, *args):
181 getalgn(f)
182 s = f.read(4)
183 if len(s) < 4:
184 raise EOFError, 'in getlong' + str(args)
185 return (ord(s[0])<<24) | (ord(s[1])<<16) | (ord(s[2])<<8) | ord(s[3])
186
187def getcode(f, *args):
188 getalgn(f)
189 s = f.read(4)
190 if len(s) < 4:
191 raise EOFError, 'in getcode' + str(args)
192 return s
193
194def getpstr(f, *args):
195 c = f.read(1)
196 if len(c) < 1:
197 raise EOFError, 'in getpstr[1]' + str(args)
198 nbytes = ord(c)
199 if nbytes == 0: return ''
200 s = f.read(nbytes)
201 if len(s) < nbytes:
202 raise EOFError, 'in getpstr[2]' + str(args)
203 return s
204
205def getalgn(f):
206 if f.tell() & 1:
207 c = f.read(1)
208 ##if c <> '\0':
209 ## print 'align:', `c`
210
211# ---- end get routines
212
213
214# ---- put various data types to a "file"
215
216def putlong(f, value):
217 putalgn(f)
218 f.write(chr((value>>24)&0xff))
219 f.write(chr((value>>16)&0xff))
220 f.write(chr((value>>8)&0xff))
221 f.write(chr(value&0xff))
222
223def putword(f, value):
224 putalgn(f)
225 f.write(chr((value>>8)&0xff))
226 f.write(chr(value&0xff))
227
228def putcode(f, value):
229 if type(value) != types.StringType or len(value) != 4:
230 raise TypeError, "ostype must be 4-char string"
231 putalgn(f)
232 f.write(value)
233
234def putpstr(f, value):
235 if type(value) != types.StringType or len(value) > 255:
236 raise TypeError, "pstr must be string <= 255 chars"
237 f.write(chr(len(value)) + value)
238
239def putalgn(f):
240 if f.tell() & 1:
241 f.write('\0')
242
243# ---- end put routines
244
245
246aekeywords = [
247 'tran',
248 'rtid',
249 'evcl',
250 'evid',
251 'addr',
252 'optk',
253 'timo',
254 'inte', # this attribute is read only - will be set in AESend
255 'esrc', # this attribute is read only
256 'miss', # this attribute is read only
257 'from' # new in 1.0.1
258]
259
260def missed(ae):
261 try:
262 desc = ae.AEGetAttributeDesc('miss', 'keyw')
263 except AE.Error, msg:
264 return None
265 return desc.data
266
267def unpackevent(ae):
268 parameters = {}
269 while 1:
270 key = missed(ae)
271 if not key: break
272 parameters[key] = unpack(ae.AEGetParamDesc(key, '****'))
273 attributes = {}
274 for key in aekeywords:
275 try:
276 desc = ae.AEGetAttributeDesc(key, '****')
277 except (AE.Error, MacOS.Error), msg:
278 if msg[0] != -1701:
279 raise sys.exc_type, sys.exc_value
280 continue
281 attributes[key] = unpack(desc)
282 return parameters, attributes
283
284def packevent(ae, parameters = {}, attributes = {}):
285 for key, value in parameters.items():
286 ae.AEPutParamDesc(key, pack(value))
287 for key, value in attributes.items():
288 ae.AEPutAttributeDesc(key, pack(value))
289
290def test():
291 target = AE.AECreateDesc('sign', 'KAHL')
292 ae = AE.AECreateAppleEvent('aevt', 'oapp', target, -1, 0)
293 print unpackevent(ae)
294
295if __name__ == '__main__':
296 test()