Donovan Preston's patch #538395, with some mods by me.
This patch makes inheritance for OSA classes work. The implementation is a
bit convoluted, but I don't immedeately see a simpler way of doing it.
I added calls to ascii() everywhere we output strings that may contain
non-ascii characters (Python has gotten very picky since the encoding
patch:-).
I also removed Donovan's different way of opening resource files: I don't
seem to need it.
diff --git a/Mac/Lib/aepack.py b/Mac/Lib/aepack.py
index f58dd33..dfb2953 100644
--- a/Mac/Lib/aepack.py
+++ b/Mac/Lib/aepack.py
@@ -24,6 +24,7 @@
import StringIO
import aetypes
from aetypes import mkenum, mktype
+import os
# These ones seem to be missing from AppleEvents
# (they're in AERegistry.h)
@@ -61,6 +62,15 @@
FSSType = macfs.FSSpecType
AliasType = macfs.AliasType
+def packkey(ae, key, value):
+ if hasattr(key, 'which'):
+ keystr = key.which
+ elif hasattr(key, 'want'):
+ keystr = key.want
+ else:
+ keystr = key
+ ae.AEPutParamDesc(keystr, pack(value))
+
def pack(x, forcetype = None):
"""Pack a python object into an AE descriptor"""
@@ -99,13 +109,18 @@
if t == DictionaryType:
record = AE.AECreateList('', 1)
for key, value in x.items():
- record.AEPutParamDesc(key, pack(value))
+ packkey(record, key, value)
+ #record.AEPutParamDesc(key, pack(value))
return record
if t == InstanceType and hasattr(x, '__aepack__'):
return x.__aepack__()
+ if hasattr(x, 'which'):
+ return AE.AECreateDesc('TEXT', x.which)
+ if hasattr(x, 'want'):
+ return AE.AECreateDesc('TEXT', x.want)
return AE.AECreateDesc('TEXT', repr(x)) # Copout
-def unpack(desc):
+def unpack(desc, formodulename=""):
"""Unpack an AE descriptor to a python object"""
t = desc.type
@@ -117,17 +132,17 @@
l = []
for i in range(desc.AECountItems()):
keyword, item = desc.AEGetNthDesc(i+1, '****')
- l.append(unpack(item))
+ l.append(unpack(item, formodulename))
return l
if t == typeAERecord:
d = {}
for i in range(desc.AECountItems()):
keyword, item = desc.AEGetNthDesc(i+1, '****')
- d[keyword] = unpack(item)
+ d[keyword] = unpack(item, formodulename)
return d
if t == typeAEText:
record = desc.AECoerceDesc('reco')
- return mkaetext(unpack(record))
+ return mkaetext(unpack(record, formodulename))
if t == typeAlias:
return macfs.RawAlias(desc.data)
# typeAppleEvent returned as unknown
@@ -153,7 +168,7 @@
return macfs.RawFSSpec(desc.data)
if t == typeInsertionLoc:
record = desc.AECoerceDesc('reco')
- return mkinsertionloc(unpack(record))
+ return mkinsertionloc(unpack(record, formodulename))
# typeInteger equal to typeLongInteger
if t == typeIntlText:
script, language = struct.unpack('hh', desc.data[:4])
@@ -177,7 +192,11 @@
return v
if t == typeObjectSpecifier:
record = desc.AECoerceDesc('reco')
- return mkobject(unpack(record))
+ # If we have been told the name of the module we are unpacking aedescs for,
+ # we can attempt to create the right type of python object from that module.
+ if formodulename:
+ return mkobjectfrommodule(unpack(record, formodulename), formodulename)
+ return mkobject(unpack(record, formodulename))
# typePict returned as unknown
# typePixelMap coerced to typeAERecord
# typePixelMapMinus returned as unknown
@@ -214,13 +233,13 @@
#
if t == 'rang':
record = desc.AECoerceDesc('reco')
- return mkrange(unpack(record))
+ return mkrange(unpack(record, formodulename))
if t == 'cmpd':
record = desc.AECoerceDesc('reco')
- return mkcomparison(unpack(record))
+ return mkcomparison(unpack(record, formodulename))
if t == 'logi':
record = desc.AECoerceDesc('reco')
- return mklogical(unpack(record))
+ return mklogical(unpack(record, formodulename))
return mkunknown(desc.type, desc.data)
def coerce(data, egdata):
@@ -311,6 +330,20 @@
return aetypes.Property(seld.type, fr)
return aetypes.ObjectSpecifier(want, form, seld, fr)
+# Note by Jack: I'm not 100% sure of the following code. This was
+# provided by Donovan Preston, but I wonder whether the assignment
+# to __class__ is safe. Moreover, shouldn't there be a better
+# initializer for the classes in the suites?
+def mkobjectfrommodule(dict, modulename):
+ want = dict['want'].type
+ module = __import__(modulename)
+ codenamemapper = module._classdeclarations
+ classtype = codenamemapper.get(want, None)
+ newobj = mkobject(dict)
+ if classtype:
+ newobj.__class__ = classtype
+ return newobj
+
def _test():
"""Test program. Pack and unpack various things"""
objs = [