baepack.py :  » Language-Interface » ChinesePython » chinesepython2.1.3-0.4 » Mac » Contrib » PythonScript » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Language Interface » ChinesePython 
ChinesePython » chinesepython2.1.3 0.4 » Mac » Contrib » PythonScript » baepack.py
"""Tools for use in AppleEvent clients and servers:
conversion between AE types and python types

pack(x) converts a Python object to an AEDesc object
unpack(desc) does the reverse
coerce(x, wanted_sample) coerces a python object to another python object
"""

#
# This code was originally written by Guido, and modified/extended by Jack
# to include the various types that were missing. The reference used is
# Apple Event Registry, chapter 9.
#

import struct
import string
import types
from string import strip
from types import *
import AE
from AppleEvents import *
import MacOS
import macfs
import StringIO
import baetypes
from baetypes import mkenum,mktype

import calldll

OSL = calldll.getlibrary('ObjectSupportLib')

# These ones seem to be missing from AppleEvents
# (they're in AERegistry.h)

#typeColorTable = 'clrt'
#typeDrawingArea = 'cdrw'
#typePixelMap = 'cpix'
#typePixelMapMinus = 'tpmm'
#typeRotation = 'trot'
#typeTextStyles = 'tsty'
#typeStyledText = 'STXT'
#typeAEText = 'tTXT'
#typeEnumeration = 'enum'

#
# Some AE types are immedeately coerced into something
# we like better (and which is equivalent)
#
unpacker_coercions = {
  typeComp : typeExtended,
  typeColorTable : typeAEList,
  typeDrawingArea : typeAERecord,
  typeFixed : typeExtended,
  typeFloat : typeExtended,
  typePixelMap : typeAERecord,
  typeRotation : typeAERecord,
  typeStyledText : typeAERecord,
  typeTextStyles : typeAERecord,
};

#
# Some python types we need in the packer:
#
AEDescType = type(AE.AECreateDesc('TEXT', ''))
_sample_fss = macfs.FSSpec(':')
_sample_alias = _sample_fss.NewAliasMinimal()
FSSType = type(_sample_fss)
AliasType = type(_sample_alias)

def pack(x, forcetype = None):
  """Pack a python object into an AE descriptor"""
#  print 'aepack', x, type(x), forcetype
#  if type(x) == TupleType:
#    forcetype, x = x
  if forcetype:
    print x, forcetype
    if type(x) is StringType:
      return AE.AECreateDesc(forcetype, x)
    else:
      return pack(x).AECoerceDesc(forcetype)
      
  if x == None:
    return AE.AECreateDesc('null', '')
    
  t = type(x)
  if t == AEDescType:
    return x
  if t == FSSType:
    return AE.AECreateDesc('fss ', x.data)
  if t == AliasType:
    return AE.AECreateDesc('alis', x.data)
  if t == IntType:
    return AE.AECreateDesc('long', struct.pack('l', x))
  if t == FloatType:
    #
    # XXXX (note by Guido) Weird thing -- Think C's "double" is 10 bytes, but
    # struct.pack('d') return 12 bytes (and struct.unpack requires
    # them, too).  The first 2 bytes seem to be repeated...
    # Probably an alignment problem
    # XXXX (note by Jack) haven't checked this under MW
    #
#    return AE.AECreateDesc('exte', struct.pack('d', x)[2:])
    return AE.AECreateDesc('exte', struct.pack('d', x))
  if t == StringType:
    return AE.AECreateDesc('TEXT', x)
  if t == ListType:
    list = AE.AECreateList('', 0)
    for item in x:
      list.AEPutDesc(0, pack(item))
    return list
  if t == DictionaryType:
    record = AE.AECreateList('', 1)
    for key, value in x.items():
      record.AEPutParamDesc(key, pack(value))
    return record
  if t == InstanceType and hasattr(x, '__aepack__'):
    return x.__aepack__()
  return AE.AECreateDesc('TEXT', repr(x)) # Copout

def unpack(desc):
  """Unpack an AE descriptor to a python object"""
  t = desc.type
#  print t
  
  if unpacker_coercions.has_key(t):
    desc = desc.AECoerceDesc(unpacker_coercions[t])
    t = desc.type # This is a guess by Jack....
  
  if t == typeAEList:
    l = []
    for i in range(desc.AECountItems()):
      keyword, item = desc.AEGetNthDesc(i+1, '****')
      l.append(unpack(item))
    return l
  if t == typeAERecord:
    d = {}
    for i in range(desc.AECountItems()):
      keyword, item = desc.AEGetNthDesc(i+1, '****')
      d[keyword] = unpack(item)
    return d
  if t == typeAEText:
    record = desc.AECoerceDesc('reco')
    return mkaetext(unpack(record))
  if t == typeAlias:
    return macfs.RawAlias(desc.data)
  # typeAppleEvent returned as unknown
  if t == typeBoolean:
    return struct.unpack('b', desc.data)[0]
  if t == typeChar:
    return desc.data
  # typeColorTable coerced to typeAEList
  # typeComp coerced to extended
  # typeData returned as unknown
  # typeDrawingArea coerced to typeAERecord
  if t == typeEnumeration:
    return mkenum(desc.data)
  # typeEPS returned as unknown
  if t == typeExtended:
#    print desc, type(desc), len(desc)
    data = desc.data
#    print `data[:8]`, type(data), len(data[:8])
#    print struct.unpack('=d', data[:8])[0]
#    print string.atoi(data), type(data), len(data)
#    print struct.calcsize(data)
    # XXX See corresponding note for pack()
#    return struct.unpack('d', data[:2] + data)[0]
    return struct.unpack('d', data[:8])[0]
  if t == typeFalse:
    return 0
  # typeFixed coerced to extended
  # typeFloat coerced to extended
  if t == typeFSS:
    return macfs.RawFSSpec(desc.data)
  if t == typeInsertionLoc:
    record = desc.AECoerceDesc('reco')
    return mkinsertionloc(unpack(record))
  # typeInteger equal to typeLongInteger
  if t == typeIntlText:
    script, language = struct.unpack('hh', desc.data[:4])
    return baetypes.IntlText(script, language, desc.data[4:])
  if t == typeIntlWritingCode:
    script, language = struct.unpack('hh', desc.data)
    return baetypes.IntlWritingCode(script, language)
  if t == typeKeyword:
    return mkkeyword(desc.data)
  # typeLongFloat is equal to typeFloat
  if t == typeLongInteger:
#    print t, struct.unpack('l', desc.data)
    return struct.unpack('l', desc.data)[0]
  if t == typeNull:
    return None
  if t == typeMagnitude:
    v = struct.unpack('l', desc.data)
    if v < 0:
      v = 0x100000000L + v
    return v
  if t == typeObjectSpecifier:
    import Res
#    print desc, type(desc)
#    print desc.__members__
#    print desc.data, desc.type
#    print unpack(desc)
#    getOSL = calldll.newcall(OSL.AEResolve, 'OSErr', 'InHandle', 'InShort')#, 'InString')
#    print 'OSL', getOSL(rdesc, 0)#, desc.data)
    record = desc.AECoerceDesc('reco')
#    print record
    return mkobject(unpack(record))
  # typePict returned as unknown
  # typePixelMap coerced to typeAERecord
  # typePixelMapMinus returned as unknown
  # typeProcessSerialNumber returned as unknown
  if t == typeQDPoint:
    v, h = struct.unpack('hh', desc.data)
    return baetypes.QDPoint(v, h)
  if t == typeQDRectangle:
    v0, h0, v1, h1 = struct.unpack('hhhh', desc.data)
    return baetypes.QDRectangle(v0, h0, v1, h1)
  if t == typeRGBColor:
    r, g, b = struct.unpack('hhh', desc.data)
    return baetypes.RGBColor(r, g, b)
  # typeRotation coerced to typeAERecord
  # typeScrapStyles returned as unknown
  # typeSessionID returned as unknown
  if t == typeShortFloat:
    return struct.unpack('f', desc.data)[0]
  if t == typeShortInteger:
#    print t, desc.data
#    print struct.unpack('h', desc.data)[0]
    return struct.unpack('h', desc.data)[0]
  # typeSMFloat identical to typeShortFloat
  # typeSMInt  indetical to typeShortInt
  # typeStyledText coerced to typeAERecord
  if t == typeTargetID:
    return mktargetid(desc.data)
  # typeTextStyles coerced to typeAERecord
  # typeTIFF returned as unknown
  if t == typeTrue:
    return 1
  if t == typeType:
#    print t, desc.data
    return mktype(desc.data)
  #
  # The following are special
  #
  if t == 'rang':
    record = desc.AECoerceDesc('reco')
    return mkrange(unpack(record))
  if t == 'cmpd':
    record = desc.AECoerceDesc('reco')
    return mkcomparison(unpack(record))
  if t == 'logi':
    record = desc.AECoerceDesc('reco')
    return mklogical(unpack(record))
  return mkunknown(desc.type, desc.data)
  
def coerce(data, egdata):
  """Coerce a python object to another type using the AE coercers"""
  pdata = pack(data)
  pegdata = pack(egdata)
  pdata = pdata.AECoerceDesc(pegdata.type)
  return unpack(pdata)

#
# Helper routines for unpack
#
def mktargetid(data):
  sessionID = getlong(data[:4])
  name = mkppcportrec(data[4:4+72])
  location = mklocationnamerec(data[76:76+36])
  rcvrName = mkppcportrec(data[112:112+72])
  return sessionID, name, location, rcvrName

def mkppcportrec(rec):
  namescript = getword(rec[:2])
  name = getpstr(rec[2:2+33])
  portkind = getword(rec[36:38])
  if portkind == 1:
    ctor = rec[38:42]
    type = rec[42:46]
    identity = (ctor, type)
  else:
    identity = getpstr(rec[38:38+33])
  return namescript, name, portkind, identity

def mklocationnamerec(rec):
  kind = getword(rec[:2])
  stuff = rec[2:]
  if kind == 0: stuff = None
  if kind == 2: stuff = getpstr(stuff)
  return kind, stuff

def mkunknown(type, data):
  return baetypes.Unknown(type, data)

def getpstr(s):
  return s[1:1+ord(s[0])]

def getlong(s):
  return (ord(s[0])<<24) | (ord(s[1])<<16) | (ord(s[2])<<8) | ord(s[3])

def getword(s):
  return (ord(s[0])<<8) | (ord(s[1])<<0)

def mkkeyword(keyword):
  return baetypes.Keyword(keyword)

def mkrange(dict):
  return baetypes.Range(dict['star'], dict['stop'])

def mkcomparison(dict):
  return baetypes.Comparison(dict['obj1'], dict['relo'].enum, dict['obj2'])

def mklogical(dict):
  return baetypes.Logical(dict['logc'], dict['term'])

def mkstyledtext(dict):
  return baetypes.StyledText(dict['ksty'], dict['ktxt'])
  
def mkaetext(dict):
  return baetypes.AEText(dict[keyAEScriptTag], dict[keyAEStyles], dict[keyAEText])
  
def mkinsertionloc(dict):
  return baetypes.InsertionLoc(dict[keyAEObject], dict[keyAEPosition])

def mkobject(dict):
  want = dict['want'].type
  form = dict['form'].enum
  seld = dict['seld']
  fr   = dict['from']
  if form in ('name', 'indx', 'rang', 'test'):
    if want == 'text': return baetypes.Text(seld, fr)
    if want == 'cha ': return baetypes.Character(seld, fr)
    if want == 'cwor': return baetypes.Word(seld, fr)
    if want == 'clin': return baetypes.Line(seld, fr)
    if want == 'cpar': return baetypes.Paragraph(seld, fr)
    if want == 'cwin': return baetypes.Window(seld, fr)
    if want == 'docu': return baetypes.Document(seld, fr)
    if want == 'file': return baetypes.File(seld, fr)
    if want == 'cins': return baetypes.InsertionPoint(seld, fr)
  if want == 'prop' and form == 'prop' and baetypes.IsType(seld):
    return baetypes.Property(seld.type, fr)
  return baetypes.ObjectSpecifier(want, form, seld, fr)

def _test():
  """Test program. Pack and unpack various things"""
  objs = [
    'a string',
    12,
    12.0,
    None,
    ['a', 'list', 'of', 'strings'],
    {'key1': 'value1', 'key2':'value2'},
    macfs.FSSpec(':'),
    macfs.FSSpec(':').NewAliasMinimal(),
    baetypes.Enum('enum'),
    baetypes.Type('type'),
    baetypes.Keyword('kwrd'),
    baetypes.Range(1, 10),
    baetypes.Comparison(1, '<   ', 10),
    baetypes.Logical('not ', 1),
    # Cannot do StyledText
    # Cannot do AEText
    baetypes.IntlText(0, 0, 'international text'),
    baetypes.IntlWritingCode(0,0),
    baetypes.QDPoint(50,100),
    baetypes.QDRectangle(50,100,150,200),
    baetypes.RGBColor(0x7000, 0x6000, 0x5000),
    baetypes.Unknown('xxxx', 'unknown type data'),
    baetypes.Character(1),
    baetypes.Character(2, baetypes.Line(2)),
  ]
  for o in objs:
    print 'BEFORE', o, `o`
    print type(o)
    packed = pack(o)
    unpacked = unpack(packed)
    print 'AFTER ', unpacked, `unpacked`
  import sys
  sys.exit(1)
  
if __name__ == '__main__':
  _test()
  
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.