Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 40775ba

Browse files
committed
Split aepack and aetypes off from aetools (it was getting too big)
Added support for all basic types mentioned in Apple Event Registry Added support for automatically-generated suites.
1 parent 5ae5fdf commit 40775ba

3 files changed

Lines changed: 898 additions & 463 deletions

File tree

Mac/Lib/toolbox/aepack.py

Lines changed: 356 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,356 @@
1+
"""Tools for use in AppleEvent clients and servers:
2+
conversion between AE types and python types
3+
4+
pack(x) converts a Python object to an AEDesc object
5+
unpack(desc) does the reverse
6+
coerce(x, wanted_sample) coerces a python object to another python object
7+
"""
8+
9+
#
10+
# This code was originally written by Guido, and modified/extended by Jack
11+
# to include the various types that were missing. The reference used is
12+
# Apple Event Registry, chapter 9.
13+
#
14+
15+
import struct
16+
import string
17+
import types
18+
from string import strip
19+
from types import *
20+
import AE
21+
from AppleEvents import *
22+
from AERegistry import *
23+
from AEObjects import *
24+
import MacOS
25+
import macfs
26+
import StringIO
27+
import aetypes
28+
from aetypes import mkenum, mktype
29+
30+
# These ones seem to be missing from AppleEvents
31+
# (they're in AERegistry.h)
32+
33+
#typeColorTable = 'clrt'
34+
#typeDrawingArea = 'cdrw'
35+
#typePixelMap = 'cpix'
36+
#typePixelMapMinus = 'tpmm'
37+
#typeRotation = 'trot'
38+
#typeTextStyles = 'tsty'
39+
#typeStyledText = 'STXT'
40+
#typeAEText = 'tTXT'
41+
#typeEnumeration = 'enum'
42+
43+
#
44+
# Some AE types are immedeately coerced into something
45+
# we like better (and which is equivalent)
46+
#
47+
unpacker_coercions = {
48+
typeComp : typeExtended,
49+
typeColorTable : typeAEList,
50+
typeDrawingArea : typeAERecord,
51+
typeFixed : typeExtended,
52+
typeFloat : typeExtended,
53+
typePixelMap : typeAERecord,
54+
typeRotation : typeAERecord,
55+
typeStyledText : typeAERecord,
56+
typeTextStyles : typeAERecord,
57+
};
58+
59+
#
60+
# Some python types we need in the packer:
61+
#
62+
AEDescType = type(AE.AECreateDesc('TEXT', ''))
63+
_sample_fss = macfs.FSSpec(':')
64+
_sample_alias = _sample_fss.NewAliasMinimal()
65+
FSSType = type(_sample_fss)
66+
AliasType = type(_sample_alias)
67+
68+
def pack(x, forcetype = None):
69+
"""Pack a python object into an AE descriptor"""
70+
71+
if forcetype:
72+
if type(x) is StringType:
73+
return AE.AECreateDesc(forcetype, x)
74+
else:
75+
return pack(x).AECoerceDesc(forcetype)
76+
77+
if x == None:
78+
return AE.AECreateDesc('null', '')
79+
80+
t = type(x)
81+
if t == AEDescType:
82+
return x
83+
if t == FSSType:
84+
return AE.AECreateDesc('fss ', x.data)
85+
if t == AliasType:
86+
return AE.AECreateDesc('alis', x.data)
87+
if t == IntType:
88+
return AE.AECreateDesc('long', struct.pack('l', x))
89+
if t == FloatType:
90+
#
91+
# XXXX (note by Guido) Weird thing -- Think C's "double" is 10 bytes, but
92+
# struct.pack('d') return 12 bytes (and struct.unpack requires
93+
# them, too). The first 2 bytes seem to be repeated...
94+
# Probably an alignment problem
95+
# XXXX (note by Jack) haven't checked this under MW
96+
#
97+
return AE.AECreateDesc('exte', struct.pack('d', x)[2:])
98+
if t == StringType:
99+
return AE.AECreateDesc('TEXT', x)
100+
if t == ListType:
101+
list = AE.AECreateList('', 0)
102+
for item in x:
103+
list.AEPutDesc(0, pack(item))
104+
return list
105+
if t == DictionaryType:
106+
record = AE.AECreateList('', 1)
107+
for key, value in x.items():
108+
record.AEPutParamDesc(key, pack(value))
109+
return record
110+
if t == InstanceType and hasattr(x, '__aepack__'):
111+
return x.__aepack__()
112+
return AE.AECreateDesc('TEXT', repr(x)) # Copout
113+
114+
def unpack(desc):
115+
"""Unpack an AE descriptor to a python object"""
116+
t = desc.type
117+
118+
if unpacker_coercions.has_key(t):
119+
desc = desc.AECoerceDesc(unpacker_coercions[t])
120+
121+
if t == typeAEList:
122+
l = []
123+
for i in range(desc.AECountItems()):
124+
keyword, item = desc.AEGetNthDesc(i+1, '****')
125+
l.append(unpack(item))
126+
return l
127+
if t == typeAERecord:
128+
d = {}
129+
for i in range(desc.AECountItems()):
130+
keyword, item = desc.AEGetNthDesc(i+1, '****')
131+
d[keyword] = unpack(item)
132+
return d
133+
if t == typeAEText:
134+
record = desc.AECoerceDesc('reco')
135+
return mkaetext(unpack(record))
136+
if t == typeAlias:
137+
return macfs.RawAlias(desc.data)
138+
# typeAppleEvent returned as unknown
139+
if t == typeBoolean:
140+
return struct.unpack('b', desc.data)[0]
141+
if t == typeChar:
142+
return desc.data
143+
# typeColorTable coerced to typeAEList
144+
# typeComp coerced to extended
145+
# typeData returned as unknown
146+
# typeDrawingArea coerced to typeAERecord
147+
if t == typeEnumeration:
148+
return mkenum(desc.data)
149+
# typeEPS returned as unknown
150+
if t == typeExtended:
151+
data = desc.data
152+
# XXX See corresponding note for pack()
153+
return struct.unpack('d', data[:2] + data)[0]
154+
if t == typeFalse:
155+
return 0
156+
# typeFixed coerced to extended
157+
# typeFloat coerced to extended
158+
if t == typeFSS:
159+
return macfs.RawFSSpec(desc.data)
160+
if t == typeInsertionLoc:
161+
record = desc.AECoerceDesc('reco')
162+
return mkinsertionloc(unpack(record))
163+
# typeInteger equal to typeLongInteger
164+
if t == typeIntlText:
165+
script, language = struct.unpack('hh', desc.data[:4])
166+
return aetypes.IntlText(script, language, desc.data[4:])
167+
if t == typeIntlWritingCode:
168+
script, language = struct.unpack('hh', desc.data)
169+
return aetypes.IntlWritingCode(script, language)
170+
if t == typeKeyword:
171+
return mkkeyword(desc.data)
172+
# typeLongFloat is equal to typeFloat
173+
if t == typeLongInteger:
174+
return struct.unpack('l', desc.data)[0]
175+
if t == typeNull:
176+
return None
177+
if t == typeMagnitude:
178+
v = struct.unpack('l', desc.data)
179+
if v < 0:
180+
v = 0x100000000L + v
181+
return v
182+
if t == typeObjectSpecifier:
183+
record = desc.AECoerceDesc('reco')
184+
return mkobject(unpack(record))
185+
# typePict returned as unknown
186+
# typePixelMap coerced to typeAERecord
187+
# typePixelMapMinus returned as unknown
188+
# typeProcessSerialNumber returned as unknown
189+
if t == typeQDPoint:
190+
v, h = struct.unpack('hh', desc.data)
191+
return aetypes.QDPoint(v, h)
192+
if t == typeQDRectangle:
193+
v0, h0, v1, h1 = struct.unpack('hhhh', desc.data)
194+
return aetypes.QDRectangle(v0, h0, v1, h1)
195+
if t == typeRGBColor:
196+
r, g, b = struct.unpack('hhh', desc.data)
197+
return aetypes.RGBColor(r, g, b)
198+
# typeRotation coerced to typeAERecord
199+
# typeScrapStyles returned as unknown
200+
# typeSessionID returned as unknown
201+
if t == typeShortFloat:
202+
return struct.unpack('f', desc.data)[0]
203+
if t == typeShortInteger:
204+
return struct.unpack('h', desc.data)[0]
205+
# typeSMFloat identical to typeShortFloat
206+
# typeSMInt indetical to typeShortInt
207+
# typeStyledText coerced to typeAERecord
208+
if t == typeTargetID:
209+
return mktargetid(desc.data)
210+
# typeTextStyles coerced to typeAERecord
211+
# typeTIFF returned as unknown
212+
if t == typeTrue:
213+
return 1
214+
if t == typeType:
215+
return mktype(desc.data)
216+
#
217+
# The following are special
218+
#
219+
if t == 'rang':
220+
record = desc.AECoerceDesc('reco')
221+
return mkrange(unpack(record))
222+
if t == 'cmpd':
223+
record = desc.AECoerceDesc('reco')
224+
return mkcomparison(unpack(record))
225+
if t == 'logi':
226+
record = desc.AECoerceDesc('reco')
227+
return mklogical(unpack(record))
228+
return mkunknown(desc.type, desc.data)
229+
230+
def coerce(data, egdata):
231+
"""Coerce a python object to another type using the AE coercers"""
232+
pdata = pack(data)
233+
pegdata = pack(egdata)
234+
pdata = pdata.AECoerceDesc(pegdata.type)
235+
return unpack(pdata)
236+
237+
#
238+
# Helper routines for unpack
239+
#
240+
def mktargetid(data):
241+
sessionID = getlong(data[:4])
242+
name = mkppcportrec(data[4:4+72])
243+
location = mklocationnamerec(data[76:76+36])
244+
rcvrName = mkppcportrec(data[112:112+72])
245+
return sessionID, name, location, rcvrName
246+
247+
def mkppcportrec(rec):
248+
namescript = getword(rec[:2])
249+
name = getpstr(rec[2:2+33])
250+
portkind = getword(rec[36:38])
251+
if portkind == 1:
252+
ctor = rec[38:42]
253+
type = rec[42:46]
254+
identity = (ctor, type)
255+
else:
256+
identity = getpstr(rec[38:38+33])
257+
return namescript, name, portkind, identity
258+
259+
def mklocationnamerec(rec):
260+
kind = getword(rec[:2])
261+
stuff = rec[2:]
262+
if kind == 0: stuff = None
263+
if kind == 2: stuff = getpstr(stuff)
264+
return kind, stuff
265+
266+
def mkunknown(type, data):
267+
return aetypes.Unknown(type, data)
268+
269+
def getpstr(s):
270+
return s[1:1+ord(s[0])]
271+
272+
def getlong(s):
273+
return (ord(s[0])<<24) | (ord(s[1])<<16) | (ord(s[2])<<8) | ord(s[3])
274+
275+
def getword(s):
276+
return (ord(s[0])<<8) | (ord(s[1])<<0)
277+
278+
def mkkeyword(keyword):
279+
return aetypes.Keyword(keyword)
280+
281+
def mkrange(dict):
282+
return aetypes.Range(dict['star'], dict['stop'])
283+
284+
def mkcomparison(dict):
285+
return aetypes.Comparison(dict['obj1'], dict['relo'].enum, dict['obj2'])
286+
287+
def mklogical(dict):
288+
return aetypes.Logical(dict['logc'], dict['term'])
289+
290+
def mkstyledtext(dict):
291+
return aetypes.StyledText(dict['ksty'], dict['ktxt'])
292+
293+
def mkaetext(dict):
294+
return aetypes.AEText(dict[keyAEScriptTag], dict[keyAEStyles], dict[keyAEText])
295+
296+
def mkinsertionloc(dict):
297+
return aetypes.InsertionLoc(dict[keyAEObject], dict[keyAEPosition])
298+
299+
def mkobject(dict):
300+
want = dict['want'].type
301+
form = dict['form'].enum
302+
seld = dict['seld']
303+
fr = dict['from']
304+
if form in ('name', 'indx', 'rang', 'test'):
305+
if want == 'text': return aetypes.Text(seld, fr)
306+
if want == 'cha ': return aetypes.Character(seld, fr)
307+
if want == 'cwor': return aetypes.Word(seld, fr)
308+
if want == 'clin': return aetypes.Line(seld, fr)
309+
if want == 'cpar': return aetypes.Paragraph(seld, fr)
310+
if want == 'cwin': return aetypes.Window(seld, fr)
311+
if want == 'docu': return aetypes.Document(seld, fr)
312+
if want == 'file': return aetypes.File(seld, fr)
313+
if want == 'cins': return aetypes.InsertionPoint(seld, fr)
314+
if want == 'prop' and form == 'prop' and aetypes.IsType(seld):
315+
return aetypes.Property(seld.type, fr)
316+
return aetypes.ObjectSpecifier(want, form, seld, fr)
317+
318+
def _test():
319+
"""Test program. Pack and unpack various things"""
320+
objs = [
321+
'a string',
322+
12,
323+
12.0,
324+
None,
325+
['a', 'list', 'of', 'strings'],
326+
{'key1': 'value1', 'key2':'value2'},
327+
macfs.FSSpec(':'),
328+
macfs.FSSpec(':').NewAliasMinimal(),
329+
aetypes.Enum('enum'),
330+
aetypes.Type('type'),
331+
aetypes.Keyword('kwrd'),
332+
aetypes.Range(1, 10),
333+
aetypes.Comparison(1, '< ', 10),
334+
aetypes.Logical('not ', 1),
335+
# Cannot do StyledText
336+
# Cannot do AEText
337+
aetypes.IntlText(0, 0, 'international text'),
338+
aetypes.IntlWritingCode(0,0),
339+
aetypes.QDPoint(50,100),
340+
aetypes.QDRectangle(50,100,150,200),
341+
aetypes.RGBColor(0x7000, 0x6000, 0x5000),
342+
aetypes.Unknown('xxxx', 'unknown type data'),
343+
aetypes.Character(1),
344+
aetypes.Character(2, aetypes.Line(2)),
345+
]
346+
for o in objs:
347+
print 'BEFORE', o, `o`
348+
packed = pack(o)
349+
unpacked = unpack(packed)
350+
print 'AFTER ', unpacked, `unpacked`
351+
import sys
352+
sys.exit(1)
353+
354+
if __name__ == '__main__':
355+
_test()
356+

0 commit comments

Comments
 (0)