symbian-qemu-0.9.1-12/python-2.6.1/Lib/plat-mac/aepack.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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 from warnings import warnpy3k
       
    16 warnpy3k("In 3.x, the aepack module is removed.", stacklevel=2)
       
    17 
       
    18 import struct
       
    19 import types
       
    20 from types import *
       
    21 from Carbon import AE
       
    22 from Carbon.AppleEvents import *
       
    23 import MacOS
       
    24 import Carbon.File
       
    25 import aetypes
       
    26 from aetypes import mkenum, ObjectSpecifier
       
    27 
       
    28 # These ones seem to be missing from AppleEvents
       
    29 # (they're in AERegistry.h)
       
    30 
       
    31 #typeColorTable = 'clrt'
       
    32 #typeDrawingArea = 'cdrw'
       
    33 #typePixelMap = 'cpix'
       
    34 #typePixelMapMinus = 'tpmm'
       
    35 #typeRotation = 'trot'
       
    36 #typeTextStyles = 'tsty'
       
    37 #typeStyledText = 'STXT'
       
    38 #typeAEText = 'tTXT'
       
    39 #typeEnumeration = 'enum'
       
    40 
       
    41 #
       
    42 # Some AE types are immedeately coerced into something
       
    43 # we like better (and which is equivalent)
       
    44 #
       
    45 unpacker_coercions = {
       
    46     typeComp : typeFloat,
       
    47     typeColorTable : typeAEList,
       
    48     typeDrawingArea : typeAERecord,
       
    49     typeFixed : typeFloat,
       
    50     typeExtended : typeFloat,
       
    51     typePixelMap : typeAERecord,
       
    52     typeRotation : typeAERecord,
       
    53     typeStyledText : typeAERecord,
       
    54     typeTextStyles : typeAERecord,
       
    55 };
       
    56 
       
    57 #
       
    58 # Some python types we need in the packer:
       
    59 #
       
    60 AEDescType = AE.AEDescType
       
    61 FSSType = Carbon.File.FSSpecType
       
    62 FSRefType = Carbon.File.FSRefType
       
    63 AliasType = Carbon.File.AliasType
       
    64 
       
    65 def packkey(ae, key, value):
       
    66     if hasattr(key, 'which'):
       
    67         keystr = key.which
       
    68     elif hasattr(key, 'want'):
       
    69         keystr = key.want
       
    70     else:
       
    71         keystr = key
       
    72     ae.AEPutParamDesc(keystr, pack(value))
       
    73 
       
    74 def pack(x, forcetype = None):
       
    75     """Pack a python object into an AE descriptor"""
       
    76 
       
    77     if forcetype:
       
    78         if type(x) is StringType:
       
    79             return AE.AECreateDesc(forcetype, x)
       
    80         else:
       
    81             return pack(x).AECoerceDesc(forcetype)
       
    82 
       
    83     if x is None:
       
    84         return AE.AECreateDesc('null', '')
       
    85 
       
    86     if isinstance(x, AEDescType):
       
    87         return x
       
    88     if isinstance(x, FSSType):
       
    89         return AE.AECreateDesc('fss ', x.data)
       
    90     if isinstance(x, FSRefType):
       
    91         return AE.AECreateDesc('fsrf', x.data)
       
    92     if isinstance(x, AliasType):
       
    93         return AE.AECreateDesc('alis', x.data)
       
    94     if isinstance(x, IntType):
       
    95         return AE.AECreateDesc('long', struct.pack('l', x))
       
    96     if isinstance(x, FloatType):
       
    97         return AE.AECreateDesc('doub', struct.pack('d', x))
       
    98     if isinstance(x, StringType):
       
    99         return AE.AECreateDesc('TEXT', x)
       
   100     if isinstance(x, UnicodeType):
       
   101         data = x.encode('utf16')
       
   102         if data[:2] == '\xfe\xff':
       
   103             data = data[2:]
       
   104         return AE.AECreateDesc('utxt', data)
       
   105     if isinstance(x, ListType):
       
   106         list = AE.AECreateList('', 0)
       
   107         for item in x:
       
   108             list.AEPutDesc(0, pack(item))
       
   109         return list
       
   110     if isinstance(x, DictionaryType):
       
   111         record = AE.AECreateList('', 1)
       
   112         for key, value in x.items():
       
   113             packkey(record, key, value)
       
   114             #record.AEPutParamDesc(key, pack(value))
       
   115         return record
       
   116     if type(x) == types.ClassType and issubclass(x, ObjectSpecifier):
       
   117         # Note: we are getting a class object here, not an instance
       
   118         return AE.AECreateDesc('type', x.want)
       
   119     if hasattr(x, '__aepack__'):
       
   120         return x.__aepack__()
       
   121     if hasattr(x, 'which'):
       
   122         return AE.AECreateDesc('TEXT', x.which)
       
   123     if hasattr(x, 'want'):
       
   124         return AE.AECreateDesc('TEXT', x.want)
       
   125     return AE.AECreateDesc('TEXT', repr(x)) # Copout
       
   126 
       
   127 def unpack(desc, formodulename=""):
       
   128     """Unpack an AE descriptor to a python object"""
       
   129     t = desc.type
       
   130 
       
   131     if unpacker_coercions.has_key(t):
       
   132         desc = desc.AECoerceDesc(unpacker_coercions[t])
       
   133         t = desc.type # This is a guess by Jack....
       
   134 
       
   135     if t == typeAEList:
       
   136         l = []
       
   137         for i in range(desc.AECountItems()):
       
   138             keyword, item = desc.AEGetNthDesc(i+1, '****')
       
   139             l.append(unpack(item, formodulename))
       
   140         return l
       
   141     if t == typeAERecord:
       
   142         d = {}
       
   143         for i in range(desc.AECountItems()):
       
   144             keyword, item = desc.AEGetNthDesc(i+1, '****')
       
   145             d[keyword] = unpack(item, formodulename)
       
   146         return d
       
   147     if t == typeAEText:
       
   148         record = desc.AECoerceDesc('reco')
       
   149         return mkaetext(unpack(record, formodulename))
       
   150     if t == typeAlias:
       
   151         return Carbon.File.Alias(rawdata=desc.data)
       
   152     # typeAppleEvent returned as unknown
       
   153     if t == typeBoolean:
       
   154         return struct.unpack('b', desc.data)[0]
       
   155     if t == typeChar:
       
   156         return desc.data
       
   157     if t == typeUnicodeText:
       
   158         return unicode(desc.data, 'utf16')
       
   159     # typeColorTable coerced to typeAEList
       
   160     # typeComp coerced to extended
       
   161     # typeData returned as unknown
       
   162     # typeDrawingArea coerced to typeAERecord
       
   163     if t == typeEnumeration:
       
   164         return mkenum(desc.data)
       
   165     # typeEPS returned as unknown
       
   166     if t == typeFalse:
       
   167         return 0
       
   168     if t == typeFloat:
       
   169         data = desc.data
       
   170         return struct.unpack('d', data)[0]
       
   171     if t == typeFSS:
       
   172         return Carbon.File.FSSpec(rawdata=desc.data)
       
   173     if t == typeFSRef:
       
   174         return Carbon.File.FSRef(rawdata=desc.data)
       
   175     if t == typeInsertionLoc:
       
   176         record = desc.AECoerceDesc('reco')
       
   177         return mkinsertionloc(unpack(record, formodulename))
       
   178     # typeInteger equal to typeLongInteger
       
   179     if t == typeIntlText:
       
   180         script, language = struct.unpack('hh', desc.data[:4])
       
   181         return aetypes.IntlText(script, language, desc.data[4:])
       
   182     if t == typeIntlWritingCode:
       
   183         script, language = struct.unpack('hh', desc.data)
       
   184         return aetypes.IntlWritingCode(script, language)
       
   185     if t == typeKeyword:
       
   186         return mkkeyword(desc.data)
       
   187     if t == typeLongInteger:
       
   188         return struct.unpack('l', desc.data)[0]
       
   189     if t == typeLongDateTime:
       
   190         a, b = struct.unpack('lL', desc.data)
       
   191         return (long(a) << 32) + b
       
   192     if t == typeNull:
       
   193         return None
       
   194     if t == typeMagnitude:
       
   195         v = struct.unpack('l', desc.data)
       
   196         if v < 0:
       
   197             v = 0x100000000L + v
       
   198         return v
       
   199     if t == typeObjectSpecifier:
       
   200         record = desc.AECoerceDesc('reco')
       
   201         # If we have been told the name of the module we are unpacking aedescs for,
       
   202         # we can attempt to create the right type of python object from that module.
       
   203         if formodulename:
       
   204             return mkobjectfrommodule(unpack(record, formodulename), formodulename)
       
   205         return mkobject(unpack(record, formodulename))
       
   206     # typePict returned as unknown
       
   207     # typePixelMap coerced to typeAERecord
       
   208     # typePixelMapMinus returned as unknown
       
   209     # typeProcessSerialNumber returned as unknown
       
   210     if t == typeQDPoint:
       
   211         v, h = struct.unpack('hh', desc.data)
       
   212         return aetypes.QDPoint(v, h)
       
   213     if t == typeQDRectangle:
       
   214         v0, h0, v1, h1 = struct.unpack('hhhh', desc.data)
       
   215         return aetypes.QDRectangle(v0, h0, v1, h1)
       
   216     if t == typeRGBColor:
       
   217         r, g, b = struct.unpack('hhh', desc.data)
       
   218         return aetypes.RGBColor(r, g, b)
       
   219     # typeRotation coerced to typeAERecord
       
   220     # typeScrapStyles returned as unknown
       
   221     # typeSessionID returned as unknown
       
   222     if t == typeShortFloat:
       
   223         return struct.unpack('f', desc.data)[0]
       
   224     if t == typeShortInteger:
       
   225         return struct.unpack('h', desc.data)[0]
       
   226     # typeSMFloat identical to typeShortFloat
       
   227     # typeSMInt indetical to typeShortInt
       
   228     # typeStyledText coerced to typeAERecord
       
   229     if t == typeTargetID:
       
   230         return mktargetid(desc.data)
       
   231     # typeTextStyles coerced to typeAERecord
       
   232     # typeTIFF returned as unknown
       
   233     if t == typeTrue:
       
   234         return 1
       
   235     if t == typeType:
       
   236         return mktype(desc.data, formodulename)
       
   237     #
       
   238     # The following are special
       
   239     #
       
   240     if t == 'rang':
       
   241         record = desc.AECoerceDesc('reco')
       
   242         return mkrange(unpack(record, formodulename))
       
   243     if t == 'cmpd':
       
   244         record = desc.AECoerceDesc('reco')
       
   245         return mkcomparison(unpack(record, formodulename))
       
   246     if t == 'logi':
       
   247         record = desc.AECoerceDesc('reco')
       
   248         return mklogical(unpack(record, formodulename))
       
   249     return mkunknown(desc.type, desc.data)
       
   250 
       
   251 def coerce(data, egdata):
       
   252     """Coerce a python object to another type using the AE coercers"""
       
   253     pdata = pack(data)
       
   254     pegdata = pack(egdata)
       
   255     pdata = pdata.AECoerceDesc(pegdata.type)
       
   256     return unpack(pdata)
       
   257 
       
   258 #
       
   259 # Helper routines for unpack
       
   260 #
       
   261 def mktargetid(data):
       
   262     sessionID = getlong(data[:4])
       
   263     name = mkppcportrec(data[4:4+72])
       
   264     location = mklocationnamerec(data[76:76+36])
       
   265     rcvrName = mkppcportrec(data[112:112+72])
       
   266     return sessionID, name, location, rcvrName
       
   267 
       
   268 def mkppcportrec(rec):
       
   269     namescript = getword(rec[:2])
       
   270     name = getpstr(rec[2:2+33])
       
   271     portkind = getword(rec[36:38])
       
   272     if portkind == 1:
       
   273         ctor = rec[38:42]
       
   274         type = rec[42:46]
       
   275         identity = (ctor, type)
       
   276     else:
       
   277         identity = getpstr(rec[38:38+33])
       
   278     return namescript, name, portkind, identity
       
   279 
       
   280 def mklocationnamerec(rec):
       
   281     kind = getword(rec[:2])
       
   282     stuff = rec[2:]
       
   283     if kind == 0: stuff = None
       
   284     if kind == 2: stuff = getpstr(stuff)
       
   285     return kind, stuff
       
   286 
       
   287 def mkunknown(type, data):
       
   288     return aetypes.Unknown(type, data)
       
   289 
       
   290 def getpstr(s):
       
   291     return s[1:1+ord(s[0])]
       
   292 
       
   293 def getlong(s):
       
   294     return (ord(s[0])<<24) | (ord(s[1])<<16) | (ord(s[2])<<8) | ord(s[3])
       
   295 
       
   296 def getword(s):
       
   297     return (ord(s[0])<<8) | (ord(s[1])<<0)
       
   298 
       
   299 def mkkeyword(keyword):
       
   300     return aetypes.Keyword(keyword)
       
   301 
       
   302 def mkrange(dict):
       
   303     return aetypes.Range(dict['star'], dict['stop'])
       
   304 
       
   305 def mkcomparison(dict):
       
   306     return aetypes.Comparison(dict['obj1'], dict['relo'].enum, dict['obj2'])
       
   307 
       
   308 def mklogical(dict):
       
   309     return aetypes.Logical(dict['logc'], dict['term'])
       
   310 
       
   311 def mkstyledtext(dict):
       
   312     return aetypes.StyledText(dict['ksty'], dict['ktxt'])
       
   313 
       
   314 def mkaetext(dict):
       
   315     return aetypes.AEText(dict[keyAEScriptTag], dict[keyAEStyles], dict[keyAEText])
       
   316 
       
   317 def mkinsertionloc(dict):
       
   318     return aetypes.InsertionLoc(dict[keyAEObject], dict[keyAEPosition])
       
   319 
       
   320 def mkobject(dict):
       
   321     want = dict['want'].type
       
   322     form = dict['form'].enum
       
   323     seld = dict['seld']
       
   324     fr   = dict['from']
       
   325     if form in ('name', 'indx', 'rang', 'test'):
       
   326         if want == 'text': return aetypes.Text(seld, fr)
       
   327         if want == 'cha ': return aetypes.Character(seld, fr)
       
   328         if want == 'cwor': return aetypes.Word(seld, fr)
       
   329         if want == 'clin': return aetypes.Line(seld, fr)
       
   330         if want == 'cpar': return aetypes.Paragraph(seld, fr)
       
   331         if want == 'cwin': return aetypes.Window(seld, fr)
       
   332         if want == 'docu': return aetypes.Document(seld, fr)
       
   333         if want == 'file': return aetypes.File(seld, fr)
       
   334         if want == 'cins': return aetypes.InsertionPoint(seld, fr)
       
   335     if want == 'prop' and form == 'prop' and aetypes.IsType(seld):
       
   336         return aetypes.Property(seld.type, fr)
       
   337     return aetypes.ObjectSpecifier(want, form, seld, fr)
       
   338 
       
   339 # Note by Jack: I'm not 100% sure of the following code. This was
       
   340 # provided by Donovan Preston, but I wonder whether the assignment
       
   341 # to __class__ is safe. Moreover, shouldn't there be a better
       
   342 # initializer for the classes in the suites?
       
   343 def mkobjectfrommodule(dict, modulename):
       
   344     if type(dict['want']) == types.ClassType and issubclass(dict['want'], ObjectSpecifier):
       
   345         # The type has already been converted to Python. Convert back:-(
       
   346         classtype = dict['want']
       
   347         dict['want'] = aetypes.mktype(classtype.want)
       
   348     want = dict['want'].type
       
   349     module = __import__(modulename)
       
   350     codenamemapper = module._classdeclarations
       
   351     classtype = codenamemapper.get(want, None)
       
   352     newobj = mkobject(dict)
       
   353     if classtype:
       
   354         assert issubclass(classtype, ObjectSpecifier)
       
   355         newobj.__class__ = classtype
       
   356     return newobj
       
   357 
       
   358 def mktype(typecode, modulename=None):
       
   359     if modulename:
       
   360         module = __import__(modulename)
       
   361         codenamemapper = module._classdeclarations
       
   362         classtype = codenamemapper.get(typecode, None)
       
   363         if classtype:
       
   364             return classtype
       
   365     return aetypes.mktype(typecode)