mirror of
https://github.com/python/cpython.git
synced 2025-11-03 03:22:27 +00:00
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.
This commit is contained in:
parent
5ae5fdf901
commit
40775bafab
3 changed files with 897 additions and 462 deletions
356
Mac/Lib/toolbox/aepack.py
Normal file
356
Mac/Lib/toolbox/aepack.py
Normal file
|
|
@ -0,0 +1,356 @@
|
||||||
|
"""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 *
|
||||||
|
from AERegistry import *
|
||||||
|
from AEObjects import *
|
||||||
|
import MacOS
|
||||||
|
import macfs
|
||||||
|
import StringIO
|
||||||
|
import aetypes
|
||||||
|
from aetypes import mkenum, mktype
|
||||||
|
|
||||||
|
# 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"""
|
||||||
|
|
||||||
|
if 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:])
|
||||||
|
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
|
||||||
|
|
||||||
|
if unpacker_coercions.has_key(t):
|
||||||
|
desc = desc.AECoerceDesc(unpacker_coercions[t])
|
||||||
|
|
||||||
|
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:
|
||||||
|
data = desc.data
|
||||||
|
# XXX See corresponding note for pack()
|
||||||
|
return struct.unpack('d', data[:2] + data)[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 aetypes.IntlText(script, language, desc.data[4:])
|
||||||
|
if t == typeIntlWritingCode:
|
||||||
|
script, language = struct.unpack('hh', desc.data)
|
||||||
|
return aetypes.IntlWritingCode(script, language)
|
||||||
|
if t == typeKeyword:
|
||||||
|
return mkkeyword(desc.data)
|
||||||
|
# typeLongFloat is equal to typeFloat
|
||||||
|
if t == typeLongInteger:
|
||||||
|
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:
|
||||||
|
record = desc.AECoerceDesc('reco')
|
||||||
|
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 aetypes.QDPoint(v, h)
|
||||||
|
if t == typeQDRectangle:
|
||||||
|
v0, h0, v1, h1 = struct.unpack('hhhh', desc.data)
|
||||||
|
return aetypes.QDRectangle(v0, h0, v1, h1)
|
||||||
|
if t == typeRGBColor:
|
||||||
|
r, g, b = struct.unpack('hhh', desc.data)
|
||||||
|
return aetypes.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:
|
||||||
|
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:
|
||||||
|
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 aetypes.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 aetypes.Keyword(keyword)
|
||||||
|
|
||||||
|
def mkrange(dict):
|
||||||
|
return aetypes.Range(dict['star'], dict['stop'])
|
||||||
|
|
||||||
|
def mkcomparison(dict):
|
||||||
|
return aetypes.Comparison(dict['obj1'], dict['relo'].enum, dict['obj2'])
|
||||||
|
|
||||||
|
def mklogical(dict):
|
||||||
|
return aetypes.Logical(dict['logc'], dict['term'])
|
||||||
|
|
||||||
|
def mkstyledtext(dict):
|
||||||
|
return aetypes.StyledText(dict['ksty'], dict['ktxt'])
|
||||||
|
|
||||||
|
def mkaetext(dict):
|
||||||
|
return aetypes.AEText(dict[keyAEScriptTag], dict[keyAEStyles], dict[keyAEText])
|
||||||
|
|
||||||
|
def mkinsertionloc(dict):
|
||||||
|
return aetypes.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 aetypes.Text(seld, fr)
|
||||||
|
if want == 'cha ': return aetypes.Character(seld, fr)
|
||||||
|
if want == 'cwor': return aetypes.Word(seld, fr)
|
||||||
|
if want == 'clin': return aetypes.Line(seld, fr)
|
||||||
|
if want == 'cpar': return aetypes.Paragraph(seld, fr)
|
||||||
|
if want == 'cwin': return aetypes.Window(seld, fr)
|
||||||
|
if want == 'docu': return aetypes.Document(seld, fr)
|
||||||
|
if want == 'file': return aetypes.File(seld, fr)
|
||||||
|
if want == 'cins': return aetypes.InsertionPoint(seld, fr)
|
||||||
|
if want == 'prop' and form == 'prop' and aetypes.IsType(seld):
|
||||||
|
return aetypes.Property(seld.type, fr)
|
||||||
|
return aetypes.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(),
|
||||||
|
aetypes.Enum('enum'),
|
||||||
|
aetypes.Type('type'),
|
||||||
|
aetypes.Keyword('kwrd'),
|
||||||
|
aetypes.Range(1, 10),
|
||||||
|
aetypes.Comparison(1, '< ', 10),
|
||||||
|
aetypes.Logical('not ', 1),
|
||||||
|
# Cannot do StyledText
|
||||||
|
# Cannot do AEText
|
||||||
|
aetypes.IntlText(0, 0, 'international text'),
|
||||||
|
aetypes.IntlWritingCode(0,0),
|
||||||
|
aetypes.QDPoint(50,100),
|
||||||
|
aetypes.QDRectangle(50,100,150,200),
|
||||||
|
aetypes.RGBColor(0x7000, 0x6000, 0x5000),
|
||||||
|
aetypes.Unknown('xxxx', 'unknown type data'),
|
||||||
|
aetypes.Character(1),
|
||||||
|
aetypes.Character(2, aetypes.Line(2)),
|
||||||
|
]
|
||||||
|
for o in objs:
|
||||||
|
print 'BEFORE', o, `o`
|
||||||
|
packed = pack(o)
|
||||||
|
unpacked = unpack(packed)
|
||||||
|
print 'AFTER ', unpacked, `unpacked`
|
||||||
|
import sys
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
_test()
|
||||||
|
|
||||||
|
|
@ -15,477 +15,22 @@ and pack(x) will create an AE object reference equivalent to AppleScript's
|
||||||
|
|
||||||
character 1 of document "foobar"
|
character 1 of document "foobar"
|
||||||
|
|
||||||
|
Some of the stuff that appears to be exported from this module comes from other
|
||||||
|
files: the pack stuff from aepack, the objects from aetypes.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
import struct
|
|
||||||
import string
|
|
||||||
from string import strip
|
|
||||||
from types import *
|
from types import *
|
||||||
import AE
|
import AE
|
||||||
|
import AppleEvents
|
||||||
import MacOS
|
import MacOS
|
||||||
import macfs
|
|
||||||
import StringIO
|
|
||||||
|
|
||||||
|
|
||||||
AEDescType = type(AE.AECreateDesc('TEXT', ''))
|
|
||||||
|
|
||||||
FSSType = type(macfs.FSSpec(':'))
|
|
||||||
|
|
||||||
|
|
||||||
def pack(x, forcetype = None):
|
|
||||||
if 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:
|
|
||||||
vol, dir, filename = x.as_tuple()
|
|
||||||
fnlen = len(filename)
|
|
||||||
header = struct.pack('hlb', vol, dir, fnlen)
|
|
||||||
padding = '\0'*(63-fnlen)
|
|
||||||
return AE.AECreateDesc('fss ', header + filename + padding)
|
|
||||||
if t == IntType:
|
|
||||||
return AE.AECreateDesc('long', struct.pack('l', x))
|
|
||||||
if t == FloatType:
|
|
||||||
# XXX 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
|
|
||||||
return AE.AECreateDesc('exte', struct.pack('d', x)[2:])
|
|
||||||
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):
|
|
||||||
t = desc.type
|
|
||||||
if t == 'TEXT':
|
|
||||||
return desc.data
|
|
||||||
if t == 'fals':
|
|
||||||
return 0
|
|
||||||
if t == 'true':
|
|
||||||
return 1
|
|
||||||
if t == 'enum':
|
|
||||||
return mkenum(desc.data)
|
|
||||||
if t == 'type':
|
|
||||||
return mktype(desc.data)
|
|
||||||
if t == 'long':
|
|
||||||
return struct.unpack('l', desc.data)[0]
|
|
||||||
if t == 'shor':
|
|
||||||
return struct.unpack('h', desc.data)[0]
|
|
||||||
if t == 'sing':
|
|
||||||
return struct.unpack('f', desc.data)[0]
|
|
||||||
if t == 'exte':
|
|
||||||
data = desc.data
|
|
||||||
# XXX See corresponding note for pack()
|
|
||||||
return struct.unpack('d', data[:2] + data)[0]
|
|
||||||
if t in ('doub', 'comp', 'magn'):
|
|
||||||
return unpack(desc.AECoerceDesc('exte'))
|
|
||||||
if t == 'null':
|
|
||||||
return None
|
|
||||||
if t == 'list':
|
|
||||||
l = []
|
|
||||||
for i in range(desc.AECountItems()):
|
|
||||||
keyword, item = desc.AEGetNthDesc(i+1, '****')
|
|
||||||
l.append(unpack(item))
|
|
||||||
return l
|
|
||||||
if t == 'reco':
|
|
||||||
d = {}
|
|
||||||
for i in range(desc.AECountItems()):
|
|
||||||
keyword, item = desc.AEGetNthDesc(i+1, '****')
|
|
||||||
d[keyword] = unpack(item)
|
|
||||||
return d
|
|
||||||
if t == 'obj ':
|
|
||||||
record = desc.AECoerceDesc('reco')
|
|
||||||
return mkobject(unpack(record))
|
|
||||||
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))
|
|
||||||
if t == 'targ':
|
|
||||||
return mktargetid(desc.data)
|
|
||||||
if t == 'alis':
|
|
||||||
# XXX Can't handle alias records yet, so coerce to FS spec...
|
|
||||||
return unpack(desc.AECoerceDesc('fss '))
|
|
||||||
if t == 'fss ':
|
|
||||||
return mkfss(desc.data)
|
|
||||||
return mkunknown(desc.type, desc.data)
|
|
||||||
|
|
||||||
|
|
||||||
def mkfss(data):
|
|
||||||
print "mkfss data =", `data`
|
|
||||||
vol, dir, fnlen = struct.unpack('hlb', data[:7])
|
|
||||||
filename = data[7:7+fnlen]
|
|
||||||
print (vol, dir, fnlen, filename)
|
|
||||||
return macfs.FSSpec((vol, dir, filename))
|
|
||||||
|
|
||||||
|
|
||||||
def mktargetid(data):
|
|
||||||
sessionID = getlong(data[:4])
|
|
||||||
name = mkppcportrec(data[4:4+72])
|
|
||||||
print len(name), `name`
|
|
||||||
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 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 mkunknown(type, data):
|
|
||||||
return Unknown(type, data)
|
|
||||||
|
|
||||||
class Unknown:
|
|
||||||
|
|
||||||
def __init__(self, type, data):
|
|
||||||
self.type = type
|
|
||||||
self.data = data
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "Unknown(%s, %s)" % (`self.type`, `self.data`)
|
|
||||||
|
|
||||||
def __aepack__(self):
|
|
||||||
return pack(self.data, self.type)
|
|
||||||
|
|
||||||
|
|
||||||
def IsSubclass(cls, base):
|
|
||||||
"""Test whether CLASS1 is the same as or a subclass of CLASS2"""
|
|
||||||
# Loop to optimize for single inheritance
|
|
||||||
while 1:
|
|
||||||
if cls is base: return 1
|
|
||||||
if len(cls.__bases__) <> 1: break
|
|
||||||
cls = cls.__bases__[0]
|
|
||||||
# Recurse to cope with multiple inheritance
|
|
||||||
for c in cls.__bases__:
|
|
||||||
if IsSubclass(c, base): return 1
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def IsInstance(x, cls):
|
|
||||||
"""Test whether OBJECT is an instance of (a subclass of) CLASS"""
|
|
||||||
return type(x) is InstanceType and IsSubclass(x.__class__, cls)
|
|
||||||
|
|
||||||
|
|
||||||
def nice(s):
|
|
||||||
if type(s) is StringType: return repr(s)
|
|
||||||
else: return str(s)
|
|
||||||
|
|
||||||
|
|
||||||
def mkenum(enum):
|
|
||||||
if IsEnum(enum): return enum
|
|
||||||
return Enum(enum)
|
|
||||||
|
|
||||||
class Enum:
|
|
||||||
|
|
||||||
def __init__(self, enum):
|
|
||||||
self.enum = "%-4.4s" % str(enum)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "Enum(%s)" % `self.enum`
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return strip(self.enum)
|
|
||||||
|
|
||||||
def __aepack__(self):
|
|
||||||
return pack(self.enum, 'enum')
|
|
||||||
|
|
||||||
def IsEnum(x):
|
|
||||||
return IsInstance(x, Enum)
|
|
||||||
|
|
||||||
|
|
||||||
def mktype(type):
|
|
||||||
if IsType(type): return type
|
|
||||||
return Type(type)
|
|
||||||
|
|
||||||
class Type:
|
|
||||||
|
|
||||||
def __init__(self, type):
|
|
||||||
self.type = "%-4.4s" % str(type)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "Type(%s)" % `self.type`
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return strip(self.type)
|
|
||||||
|
|
||||||
def __aepack__(self):
|
|
||||||
return pack(self.type, 'type')
|
|
||||||
|
|
||||||
def IsType(x):
|
|
||||||
return IsInstance(x, Type)
|
|
||||||
|
|
||||||
|
|
||||||
def mkrange(dict):
|
|
||||||
return Range(dict['star'], dict['stop'])
|
|
||||||
|
|
||||||
class Range:
|
|
||||||
|
|
||||||
def __init__(self, start, stop):
|
|
||||||
self.start = start
|
|
||||||
self.stop = stop
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "Range(%s, %s)" % (`self.start`, `self.stop`)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "%s thru %s" % (nice(self.start), nice(self.stop))
|
|
||||||
|
|
||||||
def __aepack__(self):
|
|
||||||
return pack({'star': self.start, 'stop': self.stop}, 'rang')
|
|
||||||
|
|
||||||
def IsRange(x):
|
|
||||||
return IsInstance(x, Range)
|
|
||||||
|
|
||||||
|
|
||||||
def mkcomparison(dict):
|
|
||||||
return Comparison(dict['obj1'], dict['relo'].enum, dict['obj2'])
|
|
||||||
|
|
||||||
class Comparison:
|
|
||||||
|
|
||||||
def __init__(self, obj1, relo, obj2):
|
|
||||||
self.obj1 = obj1
|
|
||||||
self.relo = "%-4.4s" % str(relo)
|
|
||||||
self.obj2 = obj2
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "Comparison(%s, %s, %s)" % (`self.obj1`, `self.relo`, `self.obj2`)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "%s %s %s" % (nice(self.obj1), strip(self.relo), nice(self.obj2))
|
|
||||||
|
|
||||||
def __aepack__(self):
|
|
||||||
return pack({'obj1': self.obj1,
|
|
||||||
'relo': mkenum(self.relo),
|
|
||||||
'obj2': self.obj2},
|
|
||||||
'cmpd')
|
|
||||||
|
|
||||||
def IsComparison(x):
|
|
||||||
return IsInstance(x, Comparison)
|
|
||||||
|
|
||||||
|
|
||||||
def mklogical(dict):
|
|
||||||
return Logical(dict['logc'], dict['term'])
|
|
||||||
|
|
||||||
class Logical:
|
|
||||||
|
|
||||||
def __init__(self, logc, term):
|
|
||||||
self.logc = "%-4.4s" % str(logc)
|
|
||||||
self.term = term
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "Logical(%s, %s)" % (`self.logc`, `self.term`)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if type(self.term) == ListType and len(self.term) == 2:
|
|
||||||
return "%s %s %s" % (nice(self.term[0]),
|
|
||||||
strip(self.logc),
|
|
||||||
nice(self.term[1]))
|
|
||||||
else:
|
|
||||||
return "%s(%s)" % (strip(self.logc), nice(self.term))
|
|
||||||
|
|
||||||
def __aepack__(self):
|
|
||||||
return pack({'logc': mkenum(self.logc), 'term': self.term}, 'logi')
|
|
||||||
|
|
||||||
def IsLogical(x):
|
|
||||||
return IsInstance(x, Logical)
|
|
||||||
|
|
||||||
|
|
||||||
class ObjectSpecifier:
|
|
||||||
|
|
||||||
"""A class for constructing and manipulation AE object specifiers in python.
|
|
||||||
|
|
||||||
An object specifier is actually a record with four fields:
|
|
||||||
|
|
||||||
key type description
|
|
||||||
--- ---- -----------
|
|
||||||
|
|
||||||
'want' type what kind of thing we want,
|
|
||||||
e.g. word, paragraph or property
|
|
||||||
|
|
||||||
'form' enum how we specify the thing(s) we want,
|
|
||||||
e.g. by index, by range, by name, or by property specifier
|
|
||||||
|
|
||||||
'seld' any which thing(s) we want,
|
|
||||||
e.g. its index, its name, or its property specifier
|
|
||||||
|
|
||||||
'from' object the object in which it is contained,
|
|
||||||
or null, meaning look for it in the application
|
|
||||||
|
|
||||||
Note that we don't call this class plain "Object", since that name
|
|
||||||
is likely to be used by the application.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, want, form, seld, fr = None):
|
|
||||||
self.want = want
|
|
||||||
self.form = form
|
|
||||||
self.seld = seld
|
|
||||||
self.fr = fr
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
s = "ObjectSpecifier(%s, %s, %s" % (`self.want`, `self.form`, `self.seld`)
|
|
||||||
if self.fr:
|
|
||||||
s = s + ", %s)" % `self.fr`
|
|
||||||
else:
|
|
||||||
s = s + ")"
|
|
||||||
return s
|
|
||||||
|
|
||||||
def __aepack__(self):
|
|
||||||
return pack({'want': mktype(self.want),
|
|
||||||
'form': mkenum(self.form),
|
|
||||||
'seld': self.seld,
|
|
||||||
'from': self.fr},
|
|
||||||
'obj ')
|
|
||||||
|
|
||||||
|
|
||||||
def IsObjectSpecifier(x):
|
|
||||||
return IsInstance(x, ObjectSpecifier)
|
|
||||||
|
|
||||||
|
|
||||||
class Property(ObjectSpecifier):
|
|
||||||
|
|
||||||
def __init__(self, which, fr = None):
|
|
||||||
ObjectSpecifier.__init__(self, 'prop', 'prop', mkenum(which), fr)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
if self.fr:
|
|
||||||
return "Property(%s, %s)" % (`self.seld.enum`, `self.fr`)
|
|
||||||
else:
|
|
||||||
return "Property(%s)" % `self.seld.enum`
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self.fr:
|
|
||||||
return "Property %s of %s" % (str(self.seld), str(self.fr))
|
|
||||||
else:
|
|
||||||
return "Property %s" % str(self.seld)
|
|
||||||
|
|
||||||
|
|
||||||
class SelectableItem(ObjectSpecifier):
|
|
||||||
|
|
||||||
def __init__(self, want, seld, fr = None):
|
|
||||||
t = type(seld)
|
|
||||||
if t == StringType:
|
|
||||||
form = 'name'
|
|
||||||
elif IsRange(seld):
|
|
||||||
form = 'rang'
|
|
||||||
elif IsComparison(seld) or IsLogical(seld):
|
|
||||||
form = 'test'
|
|
||||||
else:
|
|
||||||
form = 'indx'
|
|
||||||
ObjectSpecifier.__init__(self, want, form, seld, fr)
|
|
||||||
|
|
||||||
|
|
||||||
class ComponentItem(SelectableItem):
|
|
||||||
# Derived classes *must* set the *class attribute* 'want' to some constant
|
|
||||||
|
|
||||||
def __init__(self, which, fr = None):
|
|
||||||
SelectableItem.__init__(self, self.want, which, fr)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
if not self.fr:
|
|
||||||
return "%s(%s)" % (self.__class__.__name__, `self.seld`)
|
|
||||||
return "%s(%s, %s)" % (self.__class__.__name__, `self.seld`, `self.fr`)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
seld = self.seld
|
|
||||||
if type(seld) == StringType:
|
|
||||||
ss = repr(seld)
|
|
||||||
elif IsRange(seld):
|
|
||||||
start, stop = seld.start, seld.stop
|
|
||||||
if type(start) == InstanceType == type(stop) and \
|
|
||||||
start.__class__ == self.__class__ == stop.__class__:
|
|
||||||
ss = str(start.seld) + " thru " + str(stop.seld)
|
|
||||||
else:
|
|
||||||
ss = str(seld)
|
|
||||||
else:
|
|
||||||
ss = str(seld)
|
|
||||||
s = "%s %s" % (self.__class__.__name__, ss)
|
|
||||||
if self.fr: s = s + " of %s" % str(self.fr)
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
template = """
|
|
||||||
class %s(ComponentItem): want = '%s'
|
|
||||||
"""
|
|
||||||
|
|
||||||
exec template % ("Text", 'text')
|
|
||||||
exec template % ("Character", 'cha ')
|
|
||||||
exec template % ("Word", 'cwor')
|
|
||||||
exec template % ("Line", 'clin')
|
|
||||||
exec template % ("Paragraph", 'cpar')
|
|
||||||
exec template % ("Window", 'cwin')
|
|
||||||
exec template % ("Document", 'docu')
|
|
||||||
exec template % ("File", 'file')
|
|
||||||
exec template % ("InsertionPoint", 'cins')
|
|
||||||
|
|
||||||
|
|
||||||
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 Text(seld, fr)
|
|
||||||
if want == 'cha ': return Character(seld, fr)
|
|
||||||
if want == 'cwor': return Word(seld, fr)
|
|
||||||
if want == 'clin': return Line(seld, fr)
|
|
||||||
if want == 'cpar': return Paragraph(seld, fr)
|
|
||||||
if want == 'cwin': return Window(seld, fr)
|
|
||||||
if want == 'docu': return Document(seld, fr)
|
|
||||||
if want == 'file': return File(seld, fr)
|
|
||||||
if want == 'cins': return InsertionPoint(seld, fr)
|
|
||||||
if want == 'prop' and form == 'prop' and IsType(seld):
|
|
||||||
return Property(seld.type, fr)
|
|
||||||
return ObjectSpecifier(want, form, seld, fr)
|
|
||||||
|
|
||||||
|
from aetypes import *
|
||||||
|
from aepack import pack, unpack, coerce, AEDescType
|
||||||
|
|
||||||
# Special code to unpack an AppleEvent (which is *not* a disguised record!)
|
# Special code to unpack an AppleEvent (which is *not* a disguised record!)
|
||||||
|
# Note by Jack: No??!? If I read the docs correctly it *is*....
|
||||||
|
|
||||||
aekeywords = [
|
aekeywords = [
|
||||||
'tran',
|
'tran',
|
||||||
|
|
@ -531,8 +76,90 @@ def packevent(ae, parameters = {}, attributes = {}):
|
||||||
for key, value in attributes.items():
|
for key, value in attributes.items():
|
||||||
ae.AEPutAttributeDesc(key, pack(value))
|
ae.AEPutAttributeDesc(key, pack(value))
|
||||||
|
|
||||||
|
#
|
||||||
|
# Support routine for automatically generated Suite interfaces
|
||||||
|
#
|
||||||
|
def keysubst(arguments, keydict):
|
||||||
|
"""Replace long name keys by their 4-char counterparts, and check"""
|
||||||
|
ok = keydict.values()
|
||||||
|
for k in arguments.keys():
|
||||||
|
if keydict.has_key(k):
|
||||||
|
v = arguments[k]
|
||||||
|
del arguments[k]
|
||||||
|
arguments[keydict[k]] = v
|
||||||
|
elif k != '----' and k not in ok:
|
||||||
|
raise TypeError, 'Unknown keyword argument: %s'%k
|
||||||
|
|
||||||
|
def enumsubst(arguments, key, edict):
|
||||||
|
"""Substitute a single enum keyword argument, if it occurs"""
|
||||||
|
if not arguments.has_key(key):
|
||||||
|
return
|
||||||
|
v = arguments[key]
|
||||||
|
ok = edict.values()
|
||||||
|
if edict.has_key(v):
|
||||||
|
arguments[key] = edict[v]
|
||||||
|
elif not v in ok:
|
||||||
|
raise TypeError, 'Unknown enumerator: %s'%v
|
||||||
|
|
||||||
|
def decodeerror(arguments):
|
||||||
|
"""Create the 'best' argument for a raise MacOS.Error"""
|
||||||
|
errn = arguments['errn']
|
||||||
|
errarg = (errn, MacOS.GetErrorString(errn))
|
||||||
|
if arguments.has_key('errs'):
|
||||||
|
errarg = errarg + (arguments['errs'],)
|
||||||
|
if arguments.has_key('erob'):
|
||||||
|
errarg = errarg + (arguments['erob'],)
|
||||||
|
return errarg
|
||||||
|
|
||||||
|
class TalkTo:
|
||||||
|
"""An AE connection to an application"""
|
||||||
|
|
||||||
|
def __init__(self, signature):
|
||||||
|
"""Create a communication channel with a particular application.
|
||||||
|
|
||||||
|
Addressing the application is done by specifying either a
|
||||||
|
4-byte signature, an AEDesc or an object that will __aepack__
|
||||||
|
to an AEDesc.
|
||||||
|
"""
|
||||||
|
if type(signature) == AEDescType:
|
||||||
|
self.target = signature
|
||||||
|
elif type(signature) == InstanceType and hasattr(signature, '__aepack__'):
|
||||||
|
self.target = signature.__aepack__()
|
||||||
|
elif type(signature) == StringType and len(signature) != 4:
|
||||||
|
self.target = AE.AECreateDesc(AppleEvents.typeApplSignature, signature)
|
||||||
|
else:
|
||||||
|
raise TypeError, "signature should be 4-char string or AEDesc"
|
||||||
|
self.send_flags = AppleEvents.kAEWaitReply
|
||||||
|
self.send_priority = AppleEvents.kAENormalPriority
|
||||||
|
self.send_timeout = AppleEvents.kAEDefaultTimeout
|
||||||
|
|
||||||
|
def newevent(self, code, subcode, parameters = {}, attributes = {}):
|
||||||
|
"""Create a complete structure for an apple event"""
|
||||||
|
|
||||||
|
event = AE.AECreateAppleEvent(code, subcode, self.target,
|
||||||
|
AppleEvents.kAutoGenerateReturnID, AppleEvents.kAnyTransactionID)
|
||||||
|
packevent(event, parameters, attributes)
|
||||||
|
return event
|
||||||
|
|
||||||
|
def sendevent(self, event):
|
||||||
|
"""Send a pre-created appleevent, await the reply and unpack it"""
|
||||||
|
|
||||||
|
reply = event.AESend(self.send_flags, self.send_priority,
|
||||||
|
self.send_timeout)
|
||||||
|
parameters, attributes = unpackevent(reply)
|
||||||
|
return reply, parameters, attributes
|
||||||
|
|
||||||
|
def send(self, code, subcode, parameters = {}, attributes = {}):
|
||||||
|
"""Send an appleevent given code/subcode/pars/attrs and unpack the reply"""
|
||||||
|
return self.sendevent(self.newevent(code, subcode, parameters, attributes))
|
||||||
|
|
||||||
|
def activate(self):
|
||||||
|
"""Send 'activate' command"""
|
||||||
|
self.send('misc', 'actv')
|
||||||
|
|
||||||
|
|
||||||
# Test program
|
# Test program
|
||||||
|
# XXXX Should test more, really...
|
||||||
|
|
||||||
def test():
|
def test():
|
||||||
target = AE.AECreateDesc('sign', 'KAHL')
|
target = AE.AECreateDesc('sign', 'KAHL')
|
||||||
|
|
|
||||||
452
Mac/Lib/toolbox/aetypes.py
Normal file
452
Mac/Lib/toolbox/aetypes.py
Normal file
|
|
@ -0,0 +1,452 @@
|
||||||
|
"""aetypes - Python objects representing various AE types."""
|
||||||
|
|
||||||
|
from AppleEvents import *
|
||||||
|
from AERegistry import *
|
||||||
|
from AEObjects import *
|
||||||
|
import struct
|
||||||
|
from types import *
|
||||||
|
import string
|
||||||
|
|
||||||
|
#
|
||||||
|
# convoluted, since there are cyclic dependencies between this file and
|
||||||
|
# aetools_convert.
|
||||||
|
#
|
||||||
|
def pack(*args):
|
||||||
|
from aepack import pack
|
||||||
|
return apply(pack, args)
|
||||||
|
|
||||||
|
def IsSubclass(cls, base):
|
||||||
|
"""Test whether CLASS1 is the same as or a subclass of CLASS2"""
|
||||||
|
# Loop to optimize for single inheritance
|
||||||
|
while 1:
|
||||||
|
if cls is base: return 1
|
||||||
|
if len(cls.__bases__) <> 1: break
|
||||||
|
cls = cls.__bases__[0]
|
||||||
|
# Recurse to cope with multiple inheritance
|
||||||
|
for c in cls.__bases__:
|
||||||
|
if IsSubclass(c, base): return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def IsInstance(x, cls):
|
||||||
|
"""Test whether OBJECT is an instance of (a subclass of) CLASS"""
|
||||||
|
return type(x) is InstanceType and IsSubclass(x.__class__, cls)
|
||||||
|
|
||||||
|
def nice(s):
|
||||||
|
"""'nice' representation of an object"""
|
||||||
|
if type(s) is StringType: return repr(s)
|
||||||
|
else: return str(s)
|
||||||
|
|
||||||
|
class Unknown:
|
||||||
|
"""An uninterpreted AE object"""
|
||||||
|
|
||||||
|
def __init__(self, type, data):
|
||||||
|
self.type = type
|
||||||
|
self.data = data
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "Unknown(%s, %s)" % (`self.type`, `self.data`)
|
||||||
|
|
||||||
|
def __aepack__(self):
|
||||||
|
return pack(self.data, self.type)
|
||||||
|
|
||||||
|
class Enum:
|
||||||
|
"""An AE enumeration value"""
|
||||||
|
|
||||||
|
def __init__(self, enum):
|
||||||
|
self.enum = "%-4.4s" % str(enum)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "Enum(%s)" % `self.enum`
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return string.strip(self.enum)
|
||||||
|
|
||||||
|
def __aepack__(self):
|
||||||
|
return pack(self.enum, typeEnumeration)
|
||||||
|
|
||||||
|
def IsEnum(x):
|
||||||
|
return IsInstance(x, Enum)
|
||||||
|
|
||||||
|
def mkenum(enum):
|
||||||
|
if IsEnum(enum): return enum
|
||||||
|
return Enum(enum)
|
||||||
|
|
||||||
|
class Type:
|
||||||
|
"""An AE 4-char typename object"""
|
||||||
|
|
||||||
|
def __init__(self, type):
|
||||||
|
self.type = "%-4.4s" % str(type)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "Type(%s)" % `self.type`
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return string.strip(self.type)
|
||||||
|
|
||||||
|
def __aepack__(self):
|
||||||
|
return pack(self.type, typeType)
|
||||||
|
|
||||||
|
def IsType(x):
|
||||||
|
return IsInstance(x, Type)
|
||||||
|
|
||||||
|
def mktype(type):
|
||||||
|
if IsType(type): return type
|
||||||
|
return Type(type)
|
||||||
|
|
||||||
|
|
||||||
|
class Keyword:
|
||||||
|
"""An AE 4-char keyword object"""
|
||||||
|
|
||||||
|
def __init__(self, keyword):
|
||||||
|
self.keyword = "%-4.4s" % str(keyword)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "Keyword(%s)" % `self.keyword`
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return string.strip(self.keyword)
|
||||||
|
|
||||||
|
def __aepack__(self):
|
||||||
|
return pack(self.keyword, typeKeyword)
|
||||||
|
|
||||||
|
def IsKeyword(x):
|
||||||
|
return IsInstance(x, Keyword)
|
||||||
|
|
||||||
|
class Range:
|
||||||
|
"""An AE range object"""
|
||||||
|
|
||||||
|
def __init__(self, start, stop):
|
||||||
|
self.start = start
|
||||||
|
self.stop = stop
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "Range(%s, %s)" % (`self.start`, `self.stop`)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "%s thru %s" % (nice(self.start), nice(self.stop))
|
||||||
|
|
||||||
|
def __aepack__(self):
|
||||||
|
return pack({'star': self.start, 'stop': self.stop}, 'rang')
|
||||||
|
|
||||||
|
def IsRange(x):
|
||||||
|
return IsInstance(x, Range)
|
||||||
|
|
||||||
|
class Comparison:
|
||||||
|
"""An AE Comparison"""
|
||||||
|
|
||||||
|
def __init__(self, obj1, relo, obj2):
|
||||||
|
self.obj1 = obj1
|
||||||
|
self.relo = "%-4.4s" % str(relo)
|
||||||
|
self.obj2 = obj2
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "Comparison(%s, %s, %s)" % (`self.obj1`, `self.relo`, `self.obj2`)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "%s %s %s" % (nice(self.obj1), string.strip(self.relo), nice(self.obj2))
|
||||||
|
|
||||||
|
def __aepack__(self):
|
||||||
|
return pack({'obj1': self.obj1,
|
||||||
|
'relo': mkenum(self.relo),
|
||||||
|
'obj2': self.obj2},
|
||||||
|
'cmpd')
|
||||||
|
|
||||||
|
def IsComparison(x):
|
||||||
|
return IsInstance(x, Comparison)
|
||||||
|
|
||||||
|
class Logical:
|
||||||
|
"""An AE logical expression object"""
|
||||||
|
|
||||||
|
def __init__(self, logc, term):
|
||||||
|
self.logc = "%-4.4s" % str(logc)
|
||||||
|
self.term = term
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "Logical(%s, %s)" % (`self.logc`, `self.term`)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if type(self.term) == ListType and len(self.term) == 2:
|
||||||
|
return "%s %s %s" % (nice(self.term[0]),
|
||||||
|
string.strip(self.logc),
|
||||||
|
nice(self.term[1]))
|
||||||
|
else:
|
||||||
|
return "%s(%s)" % (string.strip(self.logc), nice(self.term))
|
||||||
|
|
||||||
|
def __aepack__(self):
|
||||||
|
return pack({'logc': mkenum(self.logc), 'term': self.term}, 'logi')
|
||||||
|
|
||||||
|
def IsLogical(x):
|
||||||
|
return IsInstance(x, Logical)
|
||||||
|
|
||||||
|
class StyledText:
|
||||||
|
"""An AE object respresenting text in a certain style"""
|
||||||
|
|
||||||
|
def __init__(self, style, text):
|
||||||
|
self.style = style
|
||||||
|
self.text = text
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "StyledText(%s, %s)" % (`self.style`, `self.text`)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.text
|
||||||
|
|
||||||
|
def __aepack__(self):
|
||||||
|
return pack({'ksty': self.style, 'ktxt': self.text}, 'STXT')
|
||||||
|
|
||||||
|
def IsStyledText(x):
|
||||||
|
return IsInstance(x, StyledText)
|
||||||
|
|
||||||
|
class AEText:
|
||||||
|
"""An AE text object with style, script and language specified"""
|
||||||
|
|
||||||
|
def __init__(self, script, style, text):
|
||||||
|
self.script = script
|
||||||
|
self.style = style
|
||||||
|
self.text = text
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "AEText(%s, %s, %s)" % (`self.script`, `self.style`, `self.text`)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.text
|
||||||
|
|
||||||
|
def __aepack__(self):
|
||||||
|
return pack({keyAEScriptTag: self.script, keyAEStyles: self.style,
|
||||||
|
keyAEText: self.text}, typeAEText)
|
||||||
|
|
||||||
|
def IsAEText(x):
|
||||||
|
return IsInstance(x, AEText)
|
||||||
|
|
||||||
|
class IntlText:
|
||||||
|
"""A text object with script and language specified"""
|
||||||
|
|
||||||
|
def __init__(self, script, language, text):
|
||||||
|
self.script = script
|
||||||
|
self.language = language
|
||||||
|
self.text = text
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "IntlText(%s, %s, %s)" % (`self.script`, `self.language`, `self.text`)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.text
|
||||||
|
|
||||||
|
def __aepack__(self):
|
||||||
|
return pack(struct.pack('hh', self.script, self.language)+self.text,
|
||||||
|
typeIntlText)
|
||||||
|
|
||||||
|
def IsIntlText(x):
|
||||||
|
return IsInstance(x, IntlText)
|
||||||
|
|
||||||
|
class IntlWritingCode:
|
||||||
|
"""An object representing script and language"""
|
||||||
|
|
||||||
|
def __init__(self, script, language):
|
||||||
|
self.script = script
|
||||||
|
self.language = language
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "IntlWritingCode(%s, %s)" % (`self.script`, `self.language`)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "script system %d, language %d"%(self.script, self.language)
|
||||||
|
|
||||||
|
def __aepack__(self):
|
||||||
|
return pack(struct.pack('hh', self.script, self.language),
|
||||||
|
typeIntlWritingCode)
|
||||||
|
|
||||||
|
def IsIntlWritingCode(x):
|
||||||
|
return IsInstance(x, IntlWritingCode)
|
||||||
|
|
||||||
|
class QDPoint:
|
||||||
|
"""A point"""
|
||||||
|
|
||||||
|
def __init__(self, v, h):
|
||||||
|
self.v = v
|
||||||
|
self.h = h
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "QDPoint(%s, %s)" % (`self.v`, `self.h`)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "(%d, %d)"%(self.v, self.h)
|
||||||
|
|
||||||
|
def __aepack__(self):
|
||||||
|
return pack(struct.pack('hh', self.v, self.h),
|
||||||
|
typeQDPoint)
|
||||||
|
|
||||||
|
def IsQDPoint(x):
|
||||||
|
return IsInstance(x, QDPoint)
|
||||||
|
|
||||||
|
class QDRectangle:
|
||||||
|
"""A rectangle"""
|
||||||
|
|
||||||
|
def __init__(self, v0, h0, v1, h1):
|
||||||
|
self.v0 = v0
|
||||||
|
self.h0 = h0
|
||||||
|
self.v1 = v1
|
||||||
|
self.h1 = h1
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "QDRectangle(%s, %s, %s, %s)" % (`self.v0`, `self.h0`,
|
||||||
|
`self.v1`, `self.h1`)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "(%d, %d)-(%d, %d)"%(self.v0, self.h0, self.v1, self.h1)
|
||||||
|
|
||||||
|
def __aepack__(self):
|
||||||
|
return pack(struct.pack('hhhh', self.v0, self.h0, self.v1, self.h1),
|
||||||
|
typeQDRectangle)
|
||||||
|
|
||||||
|
def IsQDRectangle(x):
|
||||||
|
return IsInstance(x, QDRectangle)
|
||||||
|
|
||||||
|
class RGBColor:
|
||||||
|
"""An RGB color"""
|
||||||
|
|
||||||
|
def __init__(self, r, g, b):
|
||||||
|
self.r = r
|
||||||
|
self.g = g
|
||||||
|
self.b = b
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "RGBColor(%s, %s, %s)" % (`self.r`, `self.g`, `self.b`)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "0x%x red, 0x%x green, 0x%x blue"% (self.r, self.g, self.b)
|
||||||
|
|
||||||
|
def __aepack__(self):
|
||||||
|
return pack(struct.pack('hhh', self.r, self.g, self.b),
|
||||||
|
typeRGBColor)
|
||||||
|
|
||||||
|
def IsRGBColor(x):
|
||||||
|
return IsInstance(x, RGBColor)
|
||||||
|
|
||||||
|
class ObjectSpecifier:
|
||||||
|
|
||||||
|
"""A class for constructing and manipulation AE object specifiers in python.
|
||||||
|
|
||||||
|
An object specifier is actually a record with four fields:
|
||||||
|
|
||||||
|
key type description
|
||||||
|
--- ---- -----------
|
||||||
|
|
||||||
|
'want' type what kind of thing we want,
|
||||||
|
e.g. word, paragraph or property
|
||||||
|
|
||||||
|
'form' enum how we specify the thing(s) we want,
|
||||||
|
e.g. by index, by range, by name, or by property specifier
|
||||||
|
|
||||||
|
'seld' any which thing(s) we want,
|
||||||
|
e.g. its index, its name, or its property specifier
|
||||||
|
|
||||||
|
'from' object the object in which it is contained,
|
||||||
|
or null, meaning look for it in the application
|
||||||
|
|
||||||
|
Note that we don't call this class plain "Object", since that name
|
||||||
|
is likely to be used by the application.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, want, form, seld, fr = None):
|
||||||
|
self.want = want
|
||||||
|
self.form = form
|
||||||
|
self.seld = seld
|
||||||
|
self.fr = fr
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
s = "ObjectSpecifier(%s, %s, %s" % (`self.want`, `self.form`, `self.seld`)
|
||||||
|
if self.fr:
|
||||||
|
s = s + ", %s)" % `self.fr`
|
||||||
|
else:
|
||||||
|
s = s + ")"
|
||||||
|
return s
|
||||||
|
|
||||||
|
def __aepack__(self):
|
||||||
|
return pack({'want': mktype(self.want),
|
||||||
|
'form': mkenum(self.form),
|
||||||
|
'seld': self.seld,
|
||||||
|
'from': self.fr},
|
||||||
|
'obj ')
|
||||||
|
|
||||||
|
|
||||||
|
def IsObjectSpecifier(x):
|
||||||
|
return IsInstance(x, ObjectSpecifier)
|
||||||
|
|
||||||
|
|
||||||
|
class Property(ObjectSpecifier):
|
||||||
|
|
||||||
|
def __init__(self, which, fr = None):
|
||||||
|
ObjectSpecifier.__init__(self, 'prop', 'prop', mkenum(which), fr)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
if self.fr:
|
||||||
|
return "Property(%s, %s)" % (`self.seld.enum`, `self.fr`)
|
||||||
|
else:
|
||||||
|
return "Property(%s)" % `self.seld.enum`
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.fr:
|
||||||
|
return "Property %s of %s" % (str(self.seld), str(self.fr))
|
||||||
|
else:
|
||||||
|
return "Property %s" % str(self.seld)
|
||||||
|
|
||||||
|
|
||||||
|
class SelectableItem(ObjectSpecifier):
|
||||||
|
|
||||||
|
def __init__(self, want, seld, fr = None):
|
||||||
|
t = type(seld)
|
||||||
|
if t == StringType:
|
||||||
|
form = 'name'
|
||||||
|
elif IsRange(seld):
|
||||||
|
form = 'rang'
|
||||||
|
elif IsComparison(seld) or IsLogical(seld):
|
||||||
|
form = 'test'
|
||||||
|
else:
|
||||||
|
form = 'indx'
|
||||||
|
ObjectSpecifier.__init__(self, want, form, seld, fr)
|
||||||
|
|
||||||
|
|
||||||
|
class ComponentItem(SelectableItem):
|
||||||
|
# Derived classes *must* set the *class attribute* 'want' to some constant
|
||||||
|
|
||||||
|
def __init__(self, which, fr = None):
|
||||||
|
SelectableItem.__init__(self, self.want, which, fr)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
if not self.fr:
|
||||||
|
return "%s(%s)" % (self.__class__.__name__, `self.seld`)
|
||||||
|
return "%s(%s, %s)" % (self.__class__.__name__, `self.seld`, `self.fr`)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
seld = self.seld
|
||||||
|
if type(seld) == StringType:
|
||||||
|
ss = repr(seld)
|
||||||
|
elif IsRange(seld):
|
||||||
|
start, stop = seld.start, seld.stop
|
||||||
|
if type(start) == InstanceType == type(stop) and \
|
||||||
|
start.__class__ == self.__class__ == stop.__class__:
|
||||||
|
ss = str(start.seld) + " thru " + str(stop.seld)
|
||||||
|
else:
|
||||||
|
ss = str(seld)
|
||||||
|
else:
|
||||||
|
ss = str(seld)
|
||||||
|
s = "%s %s" % (self.__class__.__name__, ss)
|
||||||
|
if self.fr: s = s + " of %s" % str(self.fr)
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
template = """
|
||||||
|
class %s(ComponentItem): want = '%s'
|
||||||
|
"""
|
||||||
|
|
||||||
|
exec template % ("Text", 'text')
|
||||||
|
exec template % ("Character", 'cha ')
|
||||||
|
exec template % ("Word", 'cwor')
|
||||||
|
exec template % ("Line", 'clin')
|
||||||
|
exec template % ("Paragraph", 'cpar')
|
||||||
|
exec template % ("Window", 'cwin')
|
||||||
|
exec template % ("Document", 'docu')
|
||||||
|
exec template % ("File", 'file')
|
||||||
|
exec template % ("InsertionPoint", 'cins')
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue