Detabbed.

This commit is contained in:
Jack Jansen 2003-04-09 13:25:43 +00:00
parent 058a84f36a
commit 0ae3220736
23 changed files with 7860 additions and 7846 deletions

View File

@ -3,119 +3,119 @@ error='Audio_mac.error'
class Play_Audio_mac:
def __init__(self, qsize=QSIZE):
self._chan = None
self._qsize = qsize
self._outrate = 22254
self._sampwidth = 1
self._nchannels = 1
self._gc = []
self._usercallback = None
def __init__(self, qsize=QSIZE):
self._chan = None
self._qsize = qsize
self._outrate = 22254
self._sampwidth = 1
self._nchannels = 1
self._gc = []
self._usercallback = None
def __del__(self):
self.stop()
self._usercallback = None
def __del__(self):
self.stop()
self._usercallback = None
def wait(self):
import time
while self.getfilled():
time.sleep(0.1)
self._chan = None
self._gc = []
def wait(self):
import time
while self.getfilled():
time.sleep(0.1)
self._chan = None
self._gc = []
def stop(self, quietNow = 1):
##chan = self._chan
self._chan = None
##chan.SndDisposeChannel(1)
self._gc = []
def stop(self, quietNow = 1):
##chan = self._chan
self._chan = None
##chan.SndDisposeChannel(1)
self._gc = []
def setoutrate(self, outrate):
self._outrate = outrate
def setoutrate(self, outrate):
self._outrate = outrate
def setsampwidth(self, sampwidth):
self._sampwidth = sampwidth
def setsampwidth(self, sampwidth):
self._sampwidth = sampwidth
def setnchannels(self, nchannels):
self._nchannels = nchannels
def setnchannels(self, nchannels):
self._nchannels = nchannels
def writeframes(self, data):
import time
from Carbon.Sound import bufferCmd, callBackCmd, extSH
import struct
import MacOS
if not self._chan:
from Carbon import Snd
self._chan = Snd.SndNewChannel(5, 0, self._callback)
nframes = len(data) / self._nchannels / self._sampwidth
if len(data) != nframes * self._nchannels * self._sampwidth:
raise error, 'data is not a whole number of frames'
while self._gc and \
self.getfilled() + nframes > \
self._qsize / self._nchannels / self._sampwidth:
time.sleep(0.1)
if self._sampwidth == 1:
import audioop
data = audioop.add(data, '\x80'*len(data), 1)
h1 = struct.pack('llHhllbbl',
id(data)+MacOS.string_id_to_buffer,
self._nchannels,
self._outrate, 0,
0,
0,
extSH,
60,
nframes)
h2 = 22*'\0'
h3 = struct.pack('hhlll',
self._sampwidth*8,
0,
0,
0,
0)
header = h1+h2+h3
self._gc.append((header, data))
self._chan.SndDoCommand((bufferCmd, 0, header), 0)
self._chan.SndDoCommand((callBackCmd, 0, 0), 0)
def writeframes(self, data):
import time
from Carbon.Sound import bufferCmd, callBackCmd, extSH
import struct
import MacOS
if not self._chan:
from Carbon import Snd
self._chan = Snd.SndNewChannel(5, 0, self._callback)
nframes = len(data) / self._nchannels / self._sampwidth
if len(data) != nframes * self._nchannels * self._sampwidth:
raise error, 'data is not a whole number of frames'
while self._gc and \
self.getfilled() + nframes > \
self._qsize / self._nchannels / self._sampwidth:
time.sleep(0.1)
if self._sampwidth == 1:
import audioop
data = audioop.add(data, '\x80'*len(data), 1)
h1 = struct.pack('llHhllbbl',
id(data)+MacOS.string_id_to_buffer,
self._nchannels,
self._outrate, 0,
0,
0,
extSH,
60,
nframes)
h2 = 22*'\0'
h3 = struct.pack('hhlll',
self._sampwidth*8,
0,
0,
0,
0)
header = h1+h2+h3
self._gc.append((header, data))
self._chan.SndDoCommand((bufferCmd, 0, header), 0)
self._chan.SndDoCommand((callBackCmd, 0, 0), 0)
def _callback(self, *args):
del self._gc[0]
if self._usercallback:
self._usercallback()
def setcallback(self, callback):
self._usercallback = callback
def _callback(self, *args):
del self._gc[0]
if self._usercallback:
self._usercallback()
def setcallback(self, callback):
self._usercallback = callback
def getfilled(self):
filled = 0
for header, data in self._gc:
filled = filled + len(data)
return filled / self._nchannels / self._sampwidth
def getfilled(self):
filled = 0
for header, data in self._gc:
filled = filled + len(data)
return filled / self._nchannels / self._sampwidth
def getfillable(self):
return (self._qsize / self._nchannels / self._sampwidth) - self.getfilled()
def getfillable(self):
return (self._qsize / self._nchannels / self._sampwidth) - self.getfilled()
def ulaw2lin(self, data):
import audioop
return audioop.ulaw2lin(data, 2)
def ulaw2lin(self, data):
import audioop
return audioop.ulaw2lin(data, 2)
def test():
import aifc
import EasyDialogs
fn = EasyDialogs.AskFileForOpen(message="Select an AIFF soundfile", typeList=("AIFF",))
if not fn: return
af = aifc.open(fn, 'r')
print af.getparams()
p = Play_Audio_mac()
p.setoutrate(af.getframerate())
p.setsampwidth(af.getsampwidth())
p.setnchannels(af.getnchannels())
BUFSIZ = 10000
while 1:
data = af.readframes(BUFSIZ)
if not data: break
p.writeframes(data)
print 'wrote', len(data), 'space', p.getfillable()
p.wait()
import aifc
import EasyDialogs
fn = EasyDialogs.AskFileForOpen(message="Select an AIFF soundfile", typeList=("AIFF",))
if not fn: return
af = aifc.open(fn, 'r')
print af.getparams()
p = Play_Audio_mac()
p.setoutrate(af.getframerate())
p.setsampwidth(af.getsampwidth())
p.setnchannels(af.getnchannels())
BUFSIZ = 10000
while 1:
data = af.readframes(BUFSIZ)
if not data: break
p.writeframes(data)
print 'wrote', len(data), 'space', p.getfillable()
p.wait()
if __name__ == '__main__':
test()
test()

View File

@ -5,53 +5,53 @@ import struct
# These needn't go through this module, but are here for completeness
def SetControlData_Handle(control, part, selector, data):
control.SetControlData_Handle(part, selector, data)
control.SetControlData_Handle(part, selector, data)
def GetControlData_Handle(control, part, selector):
return control.GetControlData_Handle(part, selector)
return control.GetControlData_Handle(part, selector)
_accessdict = {
kControlPopupButtonMenuHandleTag: (SetControlData_Handle, GetControlData_Handle),
kControlPopupButtonMenuHandleTag: (SetControlData_Handle, GetControlData_Handle),
}
_codingdict = {
kControlPushButtonDefaultTag : ("b", None, None),
kControlEditTextTextTag: (None, None, None),
kControlEditTextPasswordTag: (None, None, None),
kControlPopupButtonMenuIDTag: ("h", None, None),
kControlListBoxDoubleClickTag: ("b", None, None),
kControlPushButtonDefaultTag : ("b", None, None),
kControlEditTextTextTag: (None, None, None),
kControlEditTextPasswordTag: (None, None, None),
kControlPopupButtonMenuIDTag: ("h", None, None),
kControlListBoxDoubleClickTag: ("b", None, None),
}
def SetControlData(control, part, selector, data):
if _accessdict.has_key(selector):
setfunc, getfunc = _accessdict[selector]
setfunc(control, part, selector, data)
return
if not _codingdict.has_key(selector):
raise KeyError, ('Unknown control selector', selector)
structfmt, coder, decoder = _codingdict[selector]
if coder:
data = coder(data)
if structfmt:
data = struct.pack(structfmt, data)
control.SetControlData(part, selector, data)
if _accessdict.has_key(selector):
setfunc, getfunc = _accessdict[selector]
setfunc(control, part, selector, data)
return
if not _codingdict.has_key(selector):
raise KeyError, ('Unknown control selector', selector)
structfmt, coder, decoder = _codingdict[selector]
if coder:
data = coder(data)
if structfmt:
data = struct.pack(structfmt, data)
control.SetControlData(part, selector, data)
def GetControlData(control, part, selector):
if _accessdict.has_key(selector):
setfunc, getfunc = _accessdict[selector]
return getfunc(control, part, selector, data)
if not _codingdict.has_key(selector):
raise KeyError, ('Unknown control selector', selector)
structfmt, coder, decoder = _codingdict[selector]
data = control.GetControlData(part, selector)
if structfmt:
data = struct.unpack(structfmt, data)
if decoder:
data = decoder(data)
if type(data) == type(()) and len(data) == 1:
data = data[0]
return data
if _accessdict.has_key(selector):
setfunc, getfunc = _accessdict[selector]
return getfunc(control, part, selector, data)
if not _codingdict.has_key(selector):
raise KeyError, ('Unknown control selector', selector)
structfmt, coder, decoder = _codingdict[selector]
data = control.GetControlData(part, selector)
if structfmt:
data = struct.unpack(structfmt, data)
if decoder:
data = decoder(data)
if type(data) == type(()) and len(data) == 1:
data = data[0]
return data

View File

@ -1,4 +1,4 @@
try:
from OverrideFrom23._Res import *
from OverrideFrom23._Res import *
except ImportError:
from _Res import *
from _Res import *

View File

@ -14,202 +14,202 @@ import imgformat
# PixMap data structure element format (as used with struct)
_pmElemFormat = {
'baseAddr':'l', # address of pixel data
'rowBytes':'H', # bytes per row, plus 0x8000
'bounds':'hhhh', # coordinates imposed over pixel data
'top':'h',
'left':'h',
'bottom':'h',
'right':'h',
'pmVersion':'h', # flags for Color QuickDraw
'packType':'h', # format of compression algorithm
'packSize':'l', # size after compression
'hRes':'l', # horizontal pixels per inch
'vRes':'l', # vertical pixels per inch
'pixelType':'h', # pixel format
'pixelSize':'h', # bits per pixel
'cmpCount':'h', # color components per pixel
'cmpSize':'h', # bits per component
'planeBytes':'l', # offset in bytes to next plane
'pmTable':'l', # handle to color table
'pmReserved':'l' # reserved for future use
'baseAddr':'l', # address of pixel data
'rowBytes':'H', # bytes per row, plus 0x8000
'bounds':'hhhh', # coordinates imposed over pixel data
'top':'h',
'left':'h',
'bottom':'h',
'right':'h',
'pmVersion':'h', # flags for Color QuickDraw
'packType':'h', # format of compression algorithm
'packSize':'l', # size after compression
'hRes':'l', # horizontal pixels per inch
'vRes':'l', # vertical pixels per inch
'pixelType':'h', # pixel format
'pixelSize':'h', # bits per pixel
'cmpCount':'h', # color components per pixel
'cmpSize':'h', # bits per component
'planeBytes':'l', # offset in bytes to next plane
'pmTable':'l', # handle to color table
'pmReserved':'l' # reserved for future use
}
# PixMap data structure element offset
_pmElemOffset = {
'baseAddr':0,
'rowBytes':4,
'bounds':6,
'top':6,
'left':8,
'bottom':10,
'right':12,
'pmVersion':14,
'packType':16,
'packSize':18,
'hRes':22,
'vRes':26,
'pixelType':30,
'pixelSize':32,
'cmpCount':34,
'cmpSize':36,
'planeBytes':38,
'pmTable':42,
'pmReserved':46
'baseAddr':0,
'rowBytes':4,
'bounds':6,
'top':6,
'left':8,
'bottom':10,
'right':12,
'pmVersion':14,
'packType':16,
'packSize':18,
'hRes':22,
'vRes':26,
'pixelType':30,
'pixelSize':32,
'cmpCount':34,
'cmpSize':36,
'planeBytes':38,
'pmTable':42,
'pmReserved':46
}
class PixMapWrapper:
"""PixMapWrapper -- wraps the QD PixMap object in a Python class,
with methods to easily get/set various pixmap fields. Note: Use the
PixMap() method when passing to QD calls."""
"""PixMapWrapper -- wraps the QD PixMap object in a Python class,
with methods to easily get/set various pixmap fields. Note: Use the
PixMap() method when passing to QD calls."""
def __init__(self):
self.__dict__['data'] = ''
self._header = struct.pack("lhhhhhhhlllhhhhlll",
id(self.data)+MacOS.string_id_to_buffer,
0, # rowBytes
0, 0, 0, 0, # bounds
0, # pmVersion
0, 0, # packType, packSize
72<<16, 72<<16, # hRes, vRes
QuickDraw.RGBDirect, # pixelType
16, # pixelSize
2, 5, # cmpCount, cmpSize,
0, 0, 0) # planeBytes, pmTable, pmReserved
self.__dict__['_pm'] = Qd.RawBitMap(self._header)
def _stuff(self, element, bytes):
offset = _pmElemOffset[element]
fmt = _pmElemFormat[element]
self._header = self._header[:offset] \
+ struct.pack(fmt, bytes) \
+ self._header[offset + struct.calcsize(fmt):]
self.__dict__['_pm'] = None
def _unstuff(self, element):
offset = _pmElemOffset[element]
fmt = _pmElemFormat[element]
return struct.unpack(fmt, self._header[offset:offset+struct.calcsize(fmt)])[0]
def __init__(self):
self.__dict__['data'] = ''
self._header = struct.pack("lhhhhhhhlllhhhhlll",
id(self.data)+MacOS.string_id_to_buffer,
0, # rowBytes
0, 0, 0, 0, # bounds
0, # pmVersion
0, 0, # packType, packSize
72<<16, 72<<16, # hRes, vRes
QuickDraw.RGBDirect, # pixelType
16, # pixelSize
2, 5, # cmpCount, cmpSize,
0, 0, 0) # planeBytes, pmTable, pmReserved
self.__dict__['_pm'] = Qd.RawBitMap(self._header)
def _stuff(self, element, bytes):
offset = _pmElemOffset[element]
fmt = _pmElemFormat[element]
self._header = self._header[:offset] \
+ struct.pack(fmt, bytes) \
+ self._header[offset + struct.calcsize(fmt):]
self.__dict__['_pm'] = None
def _unstuff(self, element):
offset = _pmElemOffset[element]
fmt = _pmElemFormat[element]
return struct.unpack(fmt, self._header[offset:offset+struct.calcsize(fmt)])[0]
def __setattr__(self, attr, val):
if attr == 'baseAddr':
raise 'UseErr', "don't assign to .baseAddr -- assign to .data instead"
elif attr == 'data':
self.__dict__['data'] = val
self._stuff('baseAddr', id(self.data) + MacOS.string_id_to_buffer)
elif attr == 'rowBytes':
# high bit is always set for some odd reason
self._stuff('rowBytes', val | 0x8000)
elif attr == 'bounds':
# assume val is in official Left, Top, Right, Bottom order!
self._stuff('left',val[0])
self._stuff('top',val[1])
self._stuff('right',val[2])
self._stuff('bottom',val[3])
elif attr == 'hRes' or attr == 'vRes':
# 16.16 fixed format, so just shift 16 bits
self._stuff(attr, int(val) << 16)
elif attr in _pmElemFormat.keys():
# any other pm attribute -- just stuff
self._stuff(attr, val)
else:
self.__dict__[attr] = val
def __setattr__(self, attr, val):
if attr == 'baseAddr':
raise 'UseErr', "don't assign to .baseAddr -- assign to .data instead"
elif attr == 'data':
self.__dict__['data'] = val
self._stuff('baseAddr', id(self.data) + MacOS.string_id_to_buffer)
elif attr == 'rowBytes':
# high bit is always set for some odd reason
self._stuff('rowBytes', val | 0x8000)
elif attr == 'bounds':
# assume val is in official Left, Top, Right, Bottom order!
self._stuff('left',val[0])
self._stuff('top',val[1])
self._stuff('right',val[2])
self._stuff('bottom',val[3])
elif attr == 'hRes' or attr == 'vRes':
# 16.16 fixed format, so just shift 16 bits
self._stuff(attr, int(val) << 16)
elif attr in _pmElemFormat.keys():
# any other pm attribute -- just stuff
self._stuff(attr, val)
else:
self.__dict__[attr] = val
def __getattr__(self, attr):
if attr == 'rowBytes':
# high bit is always set for some odd reason
return self._unstuff('rowBytes') & 0x7FFF
elif attr == 'bounds':
# return bounds in official Left, Top, Right, Bottom order!
return ( \
self._unstuff('left'),
self._unstuff('top'),
self._unstuff('right'),
self._unstuff('bottom') )
elif attr == 'hRes' or attr == 'vRes':
# 16.16 fixed format, so just shift 16 bits
return self._unstuff(attr) >> 16
elif attr in _pmElemFormat.keys():
# any other pm attribute -- just unstuff
return self._unstuff(attr)
else:
return self.__dict__[attr]
def __getattr__(self, attr):
if attr == 'rowBytes':
# high bit is always set for some odd reason
return self._unstuff('rowBytes') & 0x7FFF
elif attr == 'bounds':
# return bounds in official Left, Top, Right, Bottom order!
return ( \
self._unstuff('left'),
self._unstuff('top'),
self._unstuff('right'),
self._unstuff('bottom') )
elif attr == 'hRes' or attr == 'vRes':
# 16.16 fixed format, so just shift 16 bits
return self._unstuff(attr) >> 16
elif attr in _pmElemFormat.keys():
# any other pm attribute -- just unstuff
return self._unstuff(attr)
else:
return self.__dict__[attr]
def PixMap(self):
"Return a QuickDraw PixMap corresponding to this data."
if not self.__dict__['_pm']:
self.__dict__['_pm'] = Qd.RawBitMap(self._header)
return self.__dict__['_pm']
def PixMap(self):
"Return a QuickDraw PixMap corresponding to this data."
if not self.__dict__['_pm']:
self.__dict__['_pm'] = Qd.RawBitMap(self._header)
return self.__dict__['_pm']
def blit(self, x1=0,y1=0,x2=None,y2=None, port=None):
"""Draw this pixmap into the given (default current) grafport."""
src = self.bounds
dest = [x1,y1,x2,y2]
if x2 == None:
dest[2] = x1 + src[2]-src[0]
if y2 == None:
dest[3] = y1 + src[3]-src[1]
if not port: port = Qd.GetPort()
Qd.CopyBits(self.PixMap(), port.GetPortBitMapForCopyBits(), src, tuple(dest),
QuickDraw.srcCopy, None)
def fromstring(self,s,width,height,format=imgformat.macrgb):
"""Stuff this pixmap with raw pixel data from a string.
Supply width, height, and one of the imgformat specifiers."""
# we only support 16- and 32-bit mac rgb...
# so convert if necessary
if format != imgformat.macrgb and format != imgformat.macrgb16:
# (LATER!)
raise "NotImplementedError", "conversion to macrgb or macrgb16"
self.data = s
self.bounds = (0,0,width,height)
self.cmpCount = 3
self.pixelType = QuickDraw.RGBDirect
if format == imgformat.macrgb:
self.pixelSize = 32
self.cmpSize = 8
else:
self.pixelSize = 16
self.cmpSize = 5
self.rowBytes = width*self.pixelSize/8
def blit(self, x1=0,y1=0,x2=None,y2=None, port=None):
"""Draw this pixmap into the given (default current) grafport."""
src = self.bounds
dest = [x1,y1,x2,y2]
if x2 == None:
dest[2] = x1 + src[2]-src[0]
if y2 == None:
dest[3] = y1 + src[3]-src[1]
if not port: port = Qd.GetPort()
Qd.CopyBits(self.PixMap(), port.GetPortBitMapForCopyBits(), src, tuple(dest),
QuickDraw.srcCopy, None)
def fromstring(self,s,width,height,format=imgformat.macrgb):
"""Stuff this pixmap with raw pixel data from a string.
Supply width, height, and one of the imgformat specifiers."""
# we only support 16- and 32-bit mac rgb...
# so convert if necessary
if format != imgformat.macrgb and format != imgformat.macrgb16:
# (LATER!)
raise "NotImplementedError", "conversion to macrgb or macrgb16"
self.data = s
self.bounds = (0,0,width,height)
self.cmpCount = 3
self.pixelType = QuickDraw.RGBDirect
if format == imgformat.macrgb:
self.pixelSize = 32
self.cmpSize = 8
else:
self.pixelSize = 16
self.cmpSize = 5
self.rowBytes = width*self.pixelSize/8
def tostring(self, format=imgformat.macrgb):
"""Return raw data as a string in the specified format."""
# is the native format requested? if so, just return data
if (format == imgformat.macrgb and self.pixelSize == 32) or \
(format == imgformat.macrgb16 and self.pixelsize == 16):
return self.data
# otherwise, convert to the requested format
# (LATER!)
raise "NotImplementedError", "data format conversion"
def tostring(self, format=imgformat.macrgb):
"""Return raw data as a string in the specified format."""
# is the native format requested? if so, just return data
if (format == imgformat.macrgb and self.pixelSize == 32) or \
(format == imgformat.macrgb16 and self.pixelsize == 16):
return self.data
# otherwise, convert to the requested format
# (LATER!)
raise "NotImplementedError", "data format conversion"
def fromImage(self,im):
"""Initialize this PixMap from a PIL Image object."""
# We need data in ARGB format; PIL can't currently do that,
# but it can do RGBA, which we can use by inserting one null
# up frontpm =
if im.mode != 'RGBA': im = im.convert('RGBA')
data = chr(0) + im.tostring()
self.fromstring(data, im.size[0], im.size[1])
def fromImage(self,im):
"""Initialize this PixMap from a PIL Image object."""
# We need data in ARGB format; PIL can't currently do that,
# but it can do RGBA, which we can use by inserting one null
# up frontpm =
if im.mode != 'RGBA': im = im.convert('RGBA')
data = chr(0) + im.tostring()
self.fromstring(data, im.size[0], im.size[1])
def toImage(self):
"""Return the contents of this PixMap as a PIL Image object."""
import Image
# our tostring() method returns data in ARGB format,
# whereas Image uses RGBA; a bit of slicing fixes this...
data = self.tostring()[1:] + chr(0)
bounds = self.bounds
return Image.fromstring('RGBA',(bounds[2]-bounds[0],bounds[3]-bounds[1]),data)
def toImage(self):
"""Return the contents of this PixMap as a PIL Image object."""
import Image
# our tostring() method returns data in ARGB format,
# whereas Image uses RGBA; a bit of slicing fixes this...
data = self.tostring()[1:] + chr(0)
bounds = self.bounds
return Image.fromstring('RGBA',(bounds[2]-bounds[0],bounds[3]-bounds[1]),data)
def test():
import MacOS
import EasyDialogs
import Image
path = EasyDialogs.AskFileForOpen("Image File:")
if not path: return
pm = PixMapWrapper()
pm.fromImage( Image.open(path) )
pm.blit(20,20)
return pm
import MacOS
import EasyDialogs
import Image
path = EasyDialogs.AskFileForOpen("Image File:")
if not path: return
pm = PixMapWrapper()
pm.fromImage( Image.open(path) )
pm.blit(20,20)
return pm

View File

@ -44,15 +44,15 @@ import os
# we like better (and which is equivalent)
#
unpacker_coercions = {
typeComp : typeFloat,
typeColorTable : typeAEList,
typeDrawingArea : typeAERecord,
typeFixed : typeFloat,
typeExtended : typeFloat,
typePixelMap : typeAERecord,
typeRotation : typeAERecord,
typeStyledText : typeAERecord,
typeTextStyles : typeAERecord,
typeComp : typeFloat,
typeColorTable : typeAEList,
typeDrawingArea : typeAERecord,
typeFixed : typeFloat,
typeExtended : typeFloat,
typePixelMap : typeAERecord,
typeRotation : typeAERecord,
typeStyledText : typeAERecord,
typeTextStyles : typeAERecord,
};
#
@ -64,303 +64,303 @@ FSRefType = Carbon.File.FSRefType
AliasType = Carbon.File.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))
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"""
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', '')
if isinstance(x, AEDescType):
return x
if isinstance(x, FSSType):
return AE.AECreateDesc('fss ', x.data)
if isinstance(x, FSRefType):
return AE.AECreateDesc('fsrf', x.data)
if isinstance(x, AliasType):
return AE.AECreateDesc('alis', x.data)
if isinstance(x, IntType):
return AE.AECreateDesc('long', struct.pack('l', x))
if isinstance(x, FloatType):
return AE.AECreateDesc('doub', struct.pack('d', x))
if isinstance(x, StringType):
return AE.AECreateDesc('TEXT', x)
if isinstance(x, UnicodeType):
data = x.encode('utf16')
if data[:2] == '\xfe\xff':
data = data[2:]
return AE.AECreateDesc('utxt', data)
if isinstance(x, ListType):
list = AE.AECreateList('', 0)
for item in x:
list.AEPutDesc(0, pack(item))
return list
if isinstance(x, DictionaryType):
record = AE.AECreateList('', 1)
for key, value in x.items():
packkey(record, key, value)
#record.AEPutParamDesc(key, pack(value))
return record
if type(x) == types.ClassType and issubclass(x, ObjectSpecifier):
# Note: we are getting a class object here, not an instance
return AE.AECreateDesc('type', x.want)
if 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
"""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', '')
if isinstance(x, AEDescType):
return x
if isinstance(x, FSSType):
return AE.AECreateDesc('fss ', x.data)
if isinstance(x, FSRefType):
return AE.AECreateDesc('fsrf', x.data)
if isinstance(x, AliasType):
return AE.AECreateDesc('alis', x.data)
if isinstance(x, IntType):
return AE.AECreateDesc('long', struct.pack('l', x))
if isinstance(x, FloatType):
return AE.AECreateDesc('doub', struct.pack('d', x))
if isinstance(x, StringType):
return AE.AECreateDesc('TEXT', x)
if isinstance(x, UnicodeType):
data = x.encode('utf16')
if data[:2] == '\xfe\xff':
data = data[2:]
return AE.AECreateDesc('utxt', data)
if isinstance(x, ListType):
list = AE.AECreateList('', 0)
for item in x:
list.AEPutDesc(0, pack(item))
return list
if isinstance(x, DictionaryType):
record = AE.AECreateList('', 1)
for key, value in x.items():
packkey(record, key, value)
#record.AEPutParamDesc(key, pack(value))
return record
if type(x) == types.ClassType and issubclass(x, ObjectSpecifier):
# Note: we are getting a class object here, not an instance
return AE.AECreateDesc('type', x.want)
if 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, formodulename=""):
"""Unpack an AE descriptor to a python object"""
t = desc.type
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, formodulename))
return l
if t == typeAERecord:
d = {}
for i in range(desc.AECountItems()):
keyword, item = desc.AEGetNthDesc(i+1, '****')
d[keyword] = unpack(item, formodulename)
return d
if t == typeAEText:
record = desc.AECoerceDesc('reco')
return mkaetext(unpack(record, formodulename))
if t == typeAlias:
return Carbon.File.Alias(rawdata=desc.data)
# typeAppleEvent returned as unknown
if t == typeBoolean:
return struct.unpack('b', desc.data)[0]
if t == typeChar:
return desc.data
if t == typeUnicodeText:
return unicode(desc.data, 'utf16')
# 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 == typeFalse:
return 0
if t == typeFloat:
data = desc.data
return struct.unpack('d', data)[0]
if t == typeFSS:
return Carbon.File.FSSpec(rawdata=desc.data)
if t == typeFSRef:
return Carbon.File.FSRef(rawdata=desc.data)
if t == typeInsertionLoc:
record = desc.AECoerceDesc('reco')
return mkinsertionloc(unpack(record, formodulename))
# 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)
if t == typeLongInteger:
return struct.unpack('l', desc.data)[0]
if t == typeLongDateTime:
a, b = struct.unpack('lL', desc.data)
return (long(a) << 32) + b
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')
# 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
# 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, formodulename)
#
# The following are special
#
if t == 'rang':
record = desc.AECoerceDesc('reco')
return mkrange(unpack(record, formodulename))
if t == 'cmpd':
record = desc.AECoerceDesc('reco')
return mkcomparison(unpack(record, formodulename))
if t == 'logi':
record = desc.AECoerceDesc('reco')
return mklogical(unpack(record, formodulename))
return mkunknown(desc.type, desc.data)
"""Unpack an AE descriptor to a python object"""
t = desc.type
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, formodulename))
return l
if t == typeAERecord:
d = {}
for i in range(desc.AECountItems()):
keyword, item = desc.AEGetNthDesc(i+1, '****')
d[keyword] = unpack(item, formodulename)
return d
if t == typeAEText:
record = desc.AECoerceDesc('reco')
return mkaetext(unpack(record, formodulename))
if t == typeAlias:
return Carbon.File.Alias(rawdata=desc.data)
# typeAppleEvent returned as unknown
if t == typeBoolean:
return struct.unpack('b', desc.data)[0]
if t == typeChar:
return desc.data
if t == typeUnicodeText:
return unicode(desc.data, 'utf16')
# 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 == typeFalse:
return 0
if t == typeFloat:
data = desc.data
return struct.unpack('d', data)[0]
if t == typeFSS:
return Carbon.File.FSSpec(rawdata=desc.data)
if t == typeFSRef:
return Carbon.File.FSRef(rawdata=desc.data)
if t == typeInsertionLoc:
record = desc.AECoerceDesc('reco')
return mkinsertionloc(unpack(record, formodulename))
# 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)
if t == typeLongInteger:
return struct.unpack('l', desc.data)[0]
if t == typeLongDateTime:
a, b = struct.unpack('lL', desc.data)
return (long(a) << 32) + b
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')
# 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
# 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, formodulename)
#
# The following are special
#
if t == 'rang':
record = desc.AECoerceDesc('reco')
return mkrange(unpack(record, formodulename))
if t == 'cmpd':
record = desc.AECoerceDesc('reco')
return mkcomparison(unpack(record, formodulename))
if t == 'logi':
record = desc.AECoerceDesc('reco')
return mklogical(unpack(record, formodulename))
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)
"""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
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
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
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)
return aetypes.Unknown(type, data)
def getpstr(s):
return s[1:1+ord(s[0])]
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])
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)
return (ord(s[0])<<8) | (ord(s[1])<<0)
def mkkeyword(keyword):
return aetypes.Keyword(keyword)
return aetypes.Keyword(keyword)
def mkrange(dict):
return aetypes.Range(dict['star'], dict['stop'])
return aetypes.Range(dict['star'], dict['stop'])
def mkcomparison(dict):
return aetypes.Comparison(dict['obj1'], dict['relo'].enum, dict['obj2'])
return aetypes.Comparison(dict['obj1'], dict['relo'].enum, dict['obj2'])
def mklogical(dict):
return aetypes.Logical(dict['logc'], dict['term'])
return aetypes.Logical(dict['logc'], dict['term'])
def mkstyledtext(dict):
return aetypes.StyledText(dict['ksty'], dict['ktxt'])
return aetypes.StyledText(dict['ksty'], dict['ktxt'])
def mkaetext(dict):
return aetypes.AEText(dict[keyAEScriptTag], dict[keyAEStyles], dict[keyAEText])
return aetypes.AEText(dict[keyAEScriptTag], dict[keyAEStyles], dict[keyAEText])
def mkinsertionloc(dict):
return aetypes.InsertionLoc(dict[keyAEObject], dict[keyAEPosition])
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)
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)
# 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):
if type(dict['want']) == types.ClassType and issubclass(dict['want'], ObjectSpecifier):
# The type has already been converted to Python. Convert back:-(
classtype = dict['want']
dict['want'] = aetypes.mktype(classtype.want)
want = dict['want'].type
module = __import__(modulename)
codenamemapper = module._classdeclarations
classtype = codenamemapper.get(want, None)
newobj = mkobject(dict)
if classtype:
assert issubclass(classtype, ObjectSpecifier)
newobj.__class__ = classtype
return newobj
if type(dict['want']) == types.ClassType and issubclass(dict['want'], ObjectSpecifier):
# The type has already been converted to Python. Convert back:-(
classtype = dict['want']
dict['want'] = aetypes.mktype(classtype.want)
want = dict['want'].type
module = __import__(modulename)
codenamemapper = module._classdeclarations
classtype = codenamemapper.get(want, None)
newobj = mkobject(dict)
if classtype:
assert issubclass(classtype, ObjectSpecifier)
newobj.__class__ = classtype
return newobj
def mktype(typecode, modulename=None):
if modulename:
module = __import__(modulename)
codenamemapper = module._classdeclarations
classtype = codenamemapper.get(typecode, None)
if classtype:
return classtype
return aetypes.mktype(typecode)
if modulename:
module = __import__(modulename)
codenamemapper = module._classdeclarations
classtype = codenamemapper.get(typecode, None)
if classtype:
return classtype
return aetypes.mktype(typecode)

View File

@ -9,11 +9,11 @@ unpackevent(event) returns the parameters and attributes from an AEAppleEvent re
Plus... Lots of classes and routines that help representing AE objects,
ranges, conditionals, logicals, etc., so you can write, e.g.:
x = Character(1, Document("foobar"))
x = Character(1, Document("foobar"))
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.
@ -41,306 +41,306 @@ LAUNCH_MAX_WAIT_TIME=10
# Note by Jack: No??!? If I read the docs correctly it *is*....
aekeywords = [
'tran',
'rtid',
'evcl',
'evid',
'addr',
'optk',
'timo',
'inte', # this attribute is read only - will be set in AESend
'esrc', # this attribute is read only
'miss', # this attribute is read only
'from' # new in 1.0.1
'tran',
'rtid',
'evcl',
'evid',
'addr',
'optk',
'timo',
'inte', # this attribute is read only - will be set in AESend
'esrc', # this attribute is read only
'miss', # this attribute is read only
'from' # new in 1.0.1
]
def missed(ae):
try:
desc = ae.AEGetAttributeDesc('miss', 'keyw')
except AE.Error, msg:
return None
return desc.data
try:
desc = ae.AEGetAttributeDesc('miss', 'keyw')
except AE.Error, msg:
return None
return desc.data
def unpackevent(ae, formodulename=""):
parameters = {}
try:
dirobj = ae.AEGetParamDesc('----', '****')
except AE.Error:
pass
else:
parameters['----'] = unpack(dirobj, formodulename)
del dirobj
# Workaround for what I feel is a bug in OSX 10.2: 'errn' won't show up in missed...
try:
dirobj = ae.AEGetParamDesc('errn', '****')
except AE.Error:
pass
else:
parameters['errn'] = unpack(dirobj, formodulename)
del dirobj
while 1:
key = missed(ae)
if not key: break
parameters[key] = unpack(ae.AEGetParamDesc(key, '****'), formodulename)
attributes = {}
for key in aekeywords:
try:
desc = ae.AEGetAttributeDesc(key, '****')
except (AE.Error, MacOS.Error), msg:
if msg[0] != -1701 and msg[0] != -1704:
raise
continue
attributes[key] = unpack(desc, formodulename)
return parameters, attributes
parameters = {}
try:
dirobj = ae.AEGetParamDesc('----', '****')
except AE.Error:
pass
else:
parameters['----'] = unpack(dirobj, formodulename)
del dirobj
# Workaround for what I feel is a bug in OSX 10.2: 'errn' won't show up in missed...
try:
dirobj = ae.AEGetParamDesc('errn', '****')
except AE.Error:
pass
else:
parameters['errn'] = unpack(dirobj, formodulename)
del dirobj
while 1:
key = missed(ae)
if not key: break
parameters[key] = unpack(ae.AEGetParamDesc(key, '****'), formodulename)
attributes = {}
for key in aekeywords:
try:
desc = ae.AEGetAttributeDesc(key, '****')
except (AE.Error, MacOS.Error), msg:
if msg[0] != -1701 and msg[0] != -1704:
raise
continue
attributes[key] = unpack(desc, formodulename)
return parameters, attributes
def packevent(ae, parameters = {}, attributes = {}):
for key, value in parameters.items():
packkey(ae, key, value)
for key, value in attributes.items():
ae.AEPutAttributeDesc(key, pack(value))
for key, value in parameters.items():
packkey(ae, key, value)
for key, value in attributes.items():
ae.AEPutAttributeDesc(key, pack(value))
#
# Support routine for automatically generated Suite interfaces
# These routines are also useable for the reverse function.
#
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
"""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) or edict is None:
return
v = arguments[key]
ok = edict.values()
if edict.has_key(v):
arguments[key] = Enum(edict[v])
elif not v in ok:
raise TypeError, 'Unknown enumerator: %s'%v
"""Substitute a single enum keyword argument, if it occurs"""
if not arguments.has_key(key) or edict is None:
return
v = arguments[key]
ok = edict.values()
if edict.has_key(v):
arguments[key] = Enum(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']
err_a1 = errn
if arguments.has_key('errs'):
err_a2 = arguments['errs']
else:
err_a2 = MacOS.GetErrorString(errn)
if arguments.has_key('erob'):
err_a3 = arguments['erob']
else:
err_a3 = None
return (err_a1, err_a2, err_a3)
"""Create the 'best' argument for a raise MacOS.Error"""
errn = arguments['errn']
err_a1 = errn
if arguments.has_key('errs'):
err_a2 = arguments['errs']
else:
err_a2 = MacOS.GetErrorString(errn)
if arguments.has_key('erob'):
err_a3 = arguments['erob']
else:
err_a3 = None
return (err_a1, err_a2, err_a3)
class TalkTo:
"""An AE connection to an application"""
_signature = None # Can be overridden by subclasses
_moduleName = None # Can be overridden by subclasses
__eventloop_initialized = 0
def __ensure_WMAvailable(klass):
if klass.__eventloop_initialized: return 1
if not MacOS.WMAvailable(): return 0
# Workaround for a but in MacOSX 10.2: we must have an event
# loop before we can call AESend.
Evt.WaitNextEvent(0,0)
return 1
__ensure_WMAvailable = classmethod(__ensure_WMAvailable)
"""An AE connection to an application"""
_signature = None # Can be overridden by subclasses
_moduleName = None # Can be overridden by subclasses
__eventloop_initialized = 0
def __ensure_WMAvailable(klass):
if klass.__eventloop_initialized: return 1
if not MacOS.WMAvailable(): return 0
# Workaround for a but in MacOSX 10.2: we must have an event
# loop before we can call AESend.
Evt.WaitNextEvent(0,0)
return 1
__ensure_WMAvailable = classmethod(__ensure_WMAvailable)
def __init__(self, signature=None, start=0, timeout=0):
"""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.
"""
self.target_signature = None
if signature is None:
signature = self._signature
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)
self.target_signature = signature
else:
raise TypeError, "signature should be 4-char string or AEDesc"
self.send_flags = AppleEvents.kAEWaitReply
self.send_priority = AppleEvents.kAENormalPriority
if timeout:
self.send_timeout = timeout
else:
self.send_timeout = AppleEvents.kAEDefaultTimeout
if start:
self._start()
def _start(self):
"""Start the application, if it is not running yet"""
try:
self.send('ascr', 'noop')
except AE.Error:
_launch(self.target_signature)
for i in range(LAUNCH_MAX_WAIT_TIME):
try:
self.send('ascr', 'noop')
except AE.Error:
pass
else:
break
time.sleep(1)
def start(self):
"""Deprecated, used _start()"""
self._start()
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"""
if not self.__ensure_WMAvailable():
raise RuntimeError, "No window manager access, cannot send AppleEvent"
reply = event.AESend(self.send_flags, self.send_priority,
self.send_timeout)
parameters, attributes = unpackevent(reply, self._moduleName)
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))
#
# The following events are somehow "standard" and don't seem to appear in any
# suite...
#
def activate(self):
"""Send 'activate' command"""
self.send('misc', 'actv')
def __init__(self, signature=None, start=0, timeout=0):
"""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.
"""
self.target_signature = None
if signature is None:
signature = self._signature
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)
self.target_signature = signature
else:
raise TypeError, "signature should be 4-char string or AEDesc"
self.send_flags = AppleEvents.kAEWaitReply
self.send_priority = AppleEvents.kAENormalPriority
if timeout:
self.send_timeout = timeout
else:
self.send_timeout = AppleEvents.kAEDefaultTimeout
if start:
self._start()
def _start(self):
"""Start the application, if it is not running yet"""
try:
self.send('ascr', 'noop')
except AE.Error:
_launch(self.target_signature)
for i in range(LAUNCH_MAX_WAIT_TIME):
try:
self.send('ascr', 'noop')
except AE.Error:
pass
else:
break
time.sleep(1)
def start(self):
"""Deprecated, used _start()"""
self._start()
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"""
if not self.__ensure_WMAvailable():
raise RuntimeError, "No window manager access, cannot send AppleEvent"
reply = event.AESend(self.send_flags, self.send_priority,
self.send_timeout)
parameters, attributes = unpackevent(reply, self._moduleName)
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))
#
# The following events are somehow "standard" and don't seem to appear in any
# suite...
#
def activate(self):
"""Send 'activate' command"""
self.send('misc', 'actv')
def _get(self, _object, as=None, _attributes={}):
"""_get: get data from an object
Required argument: the object
Keyword argument _attributes: AppleEvent attribute dictionary
Returns: the data
"""
_code = 'core'
_subcode = 'getd'
def _get(self, _object, as=None, _attributes={}):
"""_get: get data from an object
Required argument: the object
Keyword argument _attributes: AppleEvent attribute dictionary
Returns: the data
"""
_code = 'core'
_subcode = 'getd'
_arguments = {'----':_object}
if as:
_arguments['rtyp'] = mktype(as)
_arguments = {'----':_object}
if as:
_arguments['rtyp'] = mktype(as)
_reply, _arguments, _attributes = self.send(_code, _subcode,
_arguments, _attributes)
if _arguments.has_key('errn'):
raise Error, decodeerror(_arguments)
_reply, _arguments, _attributes = self.send(_code, _subcode,
_arguments, _attributes)
if _arguments.has_key('errn'):
raise Error, decodeerror(_arguments)
if _arguments.has_key('----'):
return _arguments['----']
if as:
item.__class__ = as
return item
get = _get
_argmap_set = {
'to' : 'data',
}
if _arguments.has_key('----'):
return _arguments['----']
if as:
item.__class__ = as
return item
get = _get
_argmap_set = {
'to' : 'data',
}
def _set(self, _object, _attributes={}, **_arguments):
"""set: Set an object's data.
Required argument: the object for the command
Keyword argument to: The new value.
Keyword argument _attributes: AppleEvent attribute dictionary
"""
_code = 'core'
_subcode = 'setd'
def _set(self, _object, _attributes={}, **_arguments):
"""set: Set an object's data.
Required argument: the object for the command
Keyword argument to: The new value.
Keyword argument _attributes: AppleEvent attribute dictionary
"""
_code = 'core'
_subcode = 'setd'
keysubst(_arguments, self._argmap_set)
_arguments['----'] = _object
keysubst(_arguments, self._argmap_set)
_arguments['----'] = _object
_reply, _arguments, _attributes = self.send(_code, _subcode,
_arguments, _attributes)
if _arguments.get('errn', 0):
raise Error, decodeerror(_arguments)
# XXXX Optionally decode result
if _arguments.has_key('----'):
return _arguments['----']
set = _set
_reply, _arguments, _attributes = self.send(_code, _subcode,
_arguments, _attributes)
if _arguments.get('errn', 0):
raise Error, decodeerror(_arguments)
# XXXX Optionally decode result
if _arguments.has_key('----'):
return _arguments['----']
set = _set
# Tiny Finder class, for local use only
class _miniFinder(TalkTo):
def open(self, _object, _attributes={}, **_arguments):
"""open: Open the specified object(s)
Required argument: list of objects to open
Keyword argument _attributes: AppleEvent attribute dictionary
"""
_code = 'aevt'
_subcode = 'odoc'
def open(self, _object, _attributes={}, **_arguments):
"""open: Open the specified object(s)
Required argument: list of objects to open
Keyword argument _attributes: AppleEvent attribute dictionary
"""
_code = 'aevt'
_subcode = 'odoc'
if _arguments: raise TypeError, 'No optional args expected'
_arguments['----'] = _object
if _arguments: raise TypeError, 'No optional args expected'
_arguments['----'] = _object
_reply, _arguments, _attributes = self.send(_code, _subcode,
_arguments, _attributes)
if _arguments.has_key('errn'):
raise Error, decodeerror(_arguments)
# XXXX Optionally decode result
if _arguments.has_key('----'):
return _arguments['----']
_reply, _arguments, _attributes = self.send(_code, _subcode,
_arguments, _attributes)
if _arguments.has_key('errn'):
raise Error, decodeerror(_arguments)
# XXXX Optionally decode result
if _arguments.has_key('----'):
return _arguments['----']
#pass
_finder = _miniFinder('MACS')
def _launch(appfile):
"""Open a file thru the finder. Specify file by name or fsspec"""
_finder.open(_application_file(('ID ', appfile)))
"""Open a file thru the finder. Specify file by name or fsspec"""
_finder.open(_application_file(('ID ', appfile)))
class _application_file(ComponentItem):
"""application file - An application's file on disk"""
want = 'appf'
"""application file - An application's file on disk"""
want = 'appf'
_application_file._propdict = {
}
_application_file._elemdict = {
}
# Test program
# XXXX Should test more, really...
def test():
target = AE.AECreateDesc('sign', 'quil')
ae = AE.AECreateAppleEvent('aevt', 'oapp', target, -1, 0)
print unpackevent(ae)
raw_input(":")
ae = AE.AECreateAppleEvent('core', 'getd', target, -1, 0)
obj = Character(2, Word(1, Document(1)))
print obj
print repr(obj)
packevent(ae, {'----': obj})
params, attrs = unpackevent(ae)
print params['----']
raw_input(":")
target = AE.AECreateDesc('sign', 'quil')
ae = AE.AECreateAppleEvent('aevt', 'oapp', target, -1, 0)
print unpackevent(ae)
raw_input(":")
ae = AE.AECreateAppleEvent('core', 'getd', target, -1, 0)
obj = Character(2, Word(1, Document(1)))
print obj
print repr(obj)
packevent(ae, {'----': obj})
params, attrs = unpackevent(ae)
print params['----']
raw_input(":")
if __name__ == '__main__':
test()
sys.exit(1)
test()
sys.exit(1)

View File

@ -10,549 +10,549 @@ import string
# aetools_convert.
#
def pack(*args, **kwargs):
from aepack import pack
return pack( *args, **kwargs)
from aepack import pack
return pack( *args, **kwargs)
def nice(s):
"""'nice' representation of an object"""
if type(s) is StringType: return repr(s)
else: return str(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)
"""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)
"""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)
return isinstance(x, Enum)
def mkenum(enum):
if IsEnum(enum): return enum
return Enum(enum)
if IsEnum(enum): return enum
return Enum(enum)
# Jack changed the way this is done
class InsertionLoc:
def __init__(self, of, pos):
self.of = of
self.pos = pos
def __repr__(self):
return "InsertionLoc(%s, %s)" % (`self.of`, `self.pos`)
def __aepack__(self):
rec = {'kobj': self.of, 'kpos': self.pos}
return pack(rec, forcetype='insl')
def __init__(self, of, pos):
self.of = of
self.pos = pos
def __repr__(self):
return "InsertionLoc(%s, %s)" % (`self.of`, `self.pos`)
def __aepack__(self):
rec = {'kobj': self.of, 'kpos': self.pos}
return pack(rec, forcetype='insl')
# Convenience functions for dsp:
def beginning(of):
return InsertionLoc(of, Enum('bgng'))
return InsertionLoc(of, Enum('bgng'))
def end(of):
return InsertionLoc(of, Enum('end '))
return InsertionLoc(of, Enum('end '))
class Boolean:
"""An AE boolean value"""
def __init__(self, bool):
self.bool = (not not bool)
def __repr__(self):
return "Boolean(%s)" % `self.bool`
def __str__(self):
if self.bool:
return "True"
else:
return "False"
def __aepack__(self):
return pack(struct.pack('b', self.bool), 'bool')
"""An AE boolean value"""
def __init__(self, bool):
self.bool = (not not bool)
def __repr__(self):
return "Boolean(%s)" % `self.bool`
def __str__(self):
if self.bool:
return "True"
else:
return "False"
def __aepack__(self):
return pack(struct.pack('b', self.bool), 'bool')
def IsBoolean(x):
return isinstance(x, Boolean)
return isinstance(x, Boolean)
def mkboolean(bool):
if IsBoolean(bool): return bool
return Boolean(bool)
if IsBoolean(bool): return bool
return Boolean(bool)
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)
"""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)
return isinstance(x, Type)
def mktype(type):
if IsType(type): return type
return Type(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)
"""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)
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')
"""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)
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')
"""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)
return isinstance(x, Comparison)
class NComparison(Comparison):
# The class attribute 'relo' must be set in a subclass
def __init__(self, obj1, obj2):
Comparison.__init__(obj1, self.relo, obj2)
# The class attribute 'relo' must be set in a subclass
def __init__(self, obj1, obj2):
Comparison.__init__(obj1, self.relo, obj2)
class Ordinal:
"""An AE Ordinal"""
def __init__(self, abso):
# self.obj1 = obj1
self.abso = "%-4.4s" % str(abso)
def __repr__(self):
return "Ordinal(%s)" % (`self.abso`)
def __str__(self):
return "%s" % (string.strip(self.abso))
def __aepack__(self):
return pack(self.abso, 'abso')
"""An AE Ordinal"""
def __init__(self, abso):
# self.obj1 = obj1
self.abso = "%-4.4s" % str(abso)
def __repr__(self):
return "Ordinal(%s)" % (`self.abso`)
def __str__(self):
return "%s" % (string.strip(self.abso))
def __aepack__(self):
return pack(self.abso, 'abso')
def IsOrdinal(x):
return isinstance(x, Ordinal)
return isinstance(x, Ordinal)
class NOrdinal(Ordinal):
# The class attribute 'abso' must be set in a subclass
def __init__(self):
Ordinal.__init__(self, self.abso)
# The class attribute 'abso' must be set in a subclass
def __init__(self):
Ordinal.__init__(self, self.abso)
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')
"""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)
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')
"""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)
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)
"""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)
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)
"""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)
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)
"""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)
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)
"""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)
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)
"""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)
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)
"""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)
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 4-char class code of thing we want,
e.g. word, paragraph or property
'form' enum how we specify which 'want' 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 ')
"""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 4-char class code of thing we want,
e.g. word, paragraph or property
'form' enum how we specify which 'want' 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)
return isinstance(x, ObjectSpecifier)
# Backwards compatability, sigh...
class Property(ObjectSpecifier):
def __init__(self, which, fr = None, want='prop'):
ObjectSpecifier.__init__(self, want, 'prop', mktype(which), fr)
def __init__(self, which, fr = None, want='prop'):
ObjectSpecifier.__init__(self, want, 'prop', mktype(which), fr)
def __repr__(self):
if self.fr:
return "Property(%s, %s)" % (`self.seld.type`, `self.fr`)
else:
return "Property(%s)" % `self.seld.type`
def __str__(self):
if self.fr:
return "Property %s of %s" % (str(self.seld), str(self.fr))
else:
return "Property %s" % str(self.seld)
def __repr__(self):
if self.fr:
return "Property(%s, %s)" % (`self.seld.type`, `self.fr`)
else:
return "Property(%s)" % `self.seld.type`
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 NProperty(ObjectSpecifier):
# Subclasses *must* self baseclass attributes:
# want is the type of this property
# which is the property name of this property
# Subclasses *must* self baseclass attributes:
# want is the type of this property
# which is the property name of this property
def __init__(self, fr = None):
#try:
# dummy = self.want
#except:
# self.want = 'prop'
self.want = 'prop'
ObjectSpecifier.__init__(self, self.want, 'prop',
mktype(self.which), fr)
def __init__(self, fr = None):
#try:
# dummy = self.want
#except:
# self.want = 'prop'
self.want = 'prop'
ObjectSpecifier.__init__(self, self.want, 'prop',
mktype(self.which), fr)
def __repr__(self):
rv = "Property(%s"%`self.seld.type`
if self.fr:
rv = rv + ", fr=%s" % `self.fr`
if self.want != 'prop':
rv = rv + ", want=%s" % `self.want`
return rv + ")"
def __str__(self):
if self.fr:
return "Property %s of %s" % (str(self.seld), str(self.fr))
else:
return "Property %s" % str(self.seld)
def __repr__(self):
rv = "Property(%s"%`self.seld.type`
if self.fr:
rv = rv + ", fr=%s" % `self.fr`
if self.want != 'prop':
rv = rv + ", want=%s" % `self.want`
return rv + ")"
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'
elif t == TupleType:
# Breakout: specify both form and seld in a tuple
# (if you want ID or rele or somesuch)
form, seld = seld
else:
form = 'indx'
ObjectSpecifier.__init__(self, want, form, seld, fr)
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'
elif t == TupleType:
# Breakout: specify both form and seld in a tuple
# (if you want ID or rele or somesuch)
form, seld = seld
else:
form = 'indx'
ObjectSpecifier.__init__(self, want, form, seld, fr)
class ComponentItem(SelectableItem):
# Derived classes *must* set the *class attribute* 'want' to some constant
# Also, dictionaries _propdict and _elemdict must be set to map property
# and element names to the correct classes
# Derived classes *must* set the *class attribute* 'want' to some constant
# Also, dictionaries _propdict and _elemdict must be set to map property
# and element names to the correct classes
_propdict = {}
_elemdict = {}
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
def __getattr__(self, name):
if self._elemdict.has_key(name):
cls = self._elemdict[name]
return DelayedComponentItem(cls, self)
if self._propdict.has_key(name):
cls = self._propdict[name]
return cls(self)
raise AttributeError, name
_propdict = {}
_elemdict = {}
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
def __getattr__(self, name):
if self._elemdict.has_key(name):
cls = self._elemdict[name]
return DelayedComponentItem(cls, self)
if self._propdict.has_key(name):
cls = self._propdict[name]
return cls(self)
raise AttributeError, name
class DelayedComponentItem:
def __init__(self, compclass, fr):
self.compclass = compclass
self.fr = fr
def __call__(self, which):
return self.compclass(which, self.fr)
def __repr__(self):
return "%s(???, %s)" % (self.__class__.__name__, `self.fr`)
def __str__(self):
return "selector for element %s of %s"%(self.__class__.__name__, str(self.fr))
def __init__(self, compclass, fr):
self.compclass = compclass
self.fr = fr
def __call__(self, which):
return self.compclass(which, self.fr)
def __repr__(self):
return "%s(???, %s)" % (self.__class__.__name__, `self.fr`)
def __str__(self):
return "selector for element %s of %s"%(self.__class__.__name__, str(self.fr))
template = """
class %s(ComponentItem): want = '%s'

View File

@ -24,77 +24,77 @@ AS_RESOURCEFORK=2
AS_IGNORE=(3,4,5,6,8,9,10,11,12,13,14,15)
def decode(input, output, resonly=0):
if type(input) == type(''):
input = open(input, 'rb')
# Should we also test for FSSpecs or FSRefs?
header = input.read(AS_HEADER_LENGTH)
try:
magic, version, dummy, nentry = struct.unpack(AS_HEADER_FORMAT, header)
except ValueError, arg:
raise Error, "Unpack header error: %s"%arg
if verbose:
print 'Magic: 0x%8.8x'%magic
print 'Version: 0x%8.8x'%version
print 'Entries: %d'%nentry
if magic != AS_MAGIC:
raise Error, 'Unknown AppleSingle magic number 0x%8.8x'%magic
if version != AS_VERSION:
raise Error, 'Unknown AppleSingle version number 0x%8.8x'%version
if nentry <= 0:
raise Error, "AppleSingle file contains no forks"
headers = [input.read(AS_ENTRY_LENGTH) for i in range(nentry)]
didwork = 0
for hdr in headers:
try:
id, offset, length = struct.unpack(AS_ENTRY_FORMAT, hdr)
except ValueError, arg:
raise Error, "Unpack entry error: %s"%arg
if verbose:
print 'Fork %d, offset %d, length %d'%(id, offset, length)
input.seek(offset)
if length == 0:
data = ''
else:
data = input.read(length)
if len(data) != length:
raise Error, 'Short read: expected %d bytes got %d'%(length, len(data))
if id == AS_DATAFORK:
if verbose:
print ' (data fork)'
if not resonly:
didwork = 1
fp = open(output, 'wb')
fp.write(data)
fp.close()
elif id == AS_RESOURCEFORK:
didwork = 1
if verbose:
print ' (resource fork)'
if resonly:
fp = open(output, 'wb')
else:
fp = MacOS.openrf(output, 'wb')
fp.write(data)
fp.close()
elif id in AS_IGNORE:
if verbose:
print ' (ignored)'
else:
raise Error, 'Unknown fork type %d'%id
if not didwork:
raise Error, 'No useful forks found'
if type(input) == type(''):
input = open(input, 'rb')
# Should we also test for FSSpecs or FSRefs?
header = input.read(AS_HEADER_LENGTH)
try:
magic, version, dummy, nentry = struct.unpack(AS_HEADER_FORMAT, header)
except ValueError, arg:
raise Error, "Unpack header error: %s"%arg
if verbose:
print 'Magic: 0x%8.8x'%magic
print 'Version: 0x%8.8x'%version
print 'Entries: %d'%nentry
if magic != AS_MAGIC:
raise Error, 'Unknown AppleSingle magic number 0x%8.8x'%magic
if version != AS_VERSION:
raise Error, 'Unknown AppleSingle version number 0x%8.8x'%version
if nentry <= 0:
raise Error, "AppleSingle file contains no forks"
headers = [input.read(AS_ENTRY_LENGTH) for i in range(nentry)]
didwork = 0
for hdr in headers:
try:
id, offset, length = struct.unpack(AS_ENTRY_FORMAT, hdr)
except ValueError, arg:
raise Error, "Unpack entry error: %s"%arg
if verbose:
print 'Fork %d, offset %d, length %d'%(id, offset, length)
input.seek(offset)
if length == 0:
data = ''
else:
data = input.read(length)
if len(data) != length:
raise Error, 'Short read: expected %d bytes got %d'%(length, len(data))
if id == AS_DATAFORK:
if verbose:
print ' (data fork)'
if not resonly:
didwork = 1
fp = open(output, 'wb')
fp.write(data)
fp.close()
elif id == AS_RESOURCEFORK:
didwork = 1
if verbose:
print ' (resource fork)'
if resonly:
fp = open(output, 'wb')
else:
fp = MacOS.openrf(output, 'wb')
fp.write(data)
fp.close()
elif id in AS_IGNORE:
if verbose:
print ' (ignored)'
else:
raise Error, 'Unknown fork type %d'%id
if not didwork:
raise Error, 'No useful forks found'
def _test():
if len(sys.argv) < 3 or sys.argv[1] == '-r' and len(sys.argv) != 4:
print 'Usage: applesingle.py [-r] applesinglefile decodedfile'
sys.exit(1)
if sys.argv[1] == '-r':
resonly = 1
del sys.argv[1]
else:
resonly = 0
decode(sys.argv[1], sys.argv[2], resonly=resonly)
if len(sys.argv) < 3 or sys.argv[1] == '-r' and len(sys.argv) != 4:
print 'Usage: applesingle.py [-r] applesinglefile decodedfile'
sys.exit(1)
if sys.argv[1] == '-r':
resonly = 1
del sys.argv[1]
else:
resonly = 0
decode(sys.argv[1], sys.argv[2], resonly=resonly)
if __name__ == '__main__':
_test()
_test()

View File

@ -14,13 +14,13 @@ import marshal
# directory.
#
if not sys.argv or sys.argv[0][:1] == '-':
# Insert our (guessed) name.
_dir = os.path.split(sys.executable)[0] # removes "python"
_dir = os.path.split(_dir)[0] # Removes "MacOS"
_dir = os.path.join(_dir, 'Resources')
sys.argv.insert(0, '__rawmain__')
# Insert our (guessed) name.
_dir = os.path.split(sys.executable)[0] # removes "python"
_dir = os.path.split(_dir)[0] # Removes "MacOS"
_dir = os.path.join(_dir, 'Resources')
sys.argv.insert(0, '__rawmain__')
else:
_dir = os.path.split(sys.argv[0])[0]
_dir = os.path.split(sys.argv[0])[0]
#
# Add the Resources directory to the path. This is where files installed
# by BuildApplet.py with the --extra option show up, and if those files are
@ -36,28 +36,28 @@ argvemulator.ArgvCollector().mainloop()
#
__file__ = os.path.join(_dir, '__main__.py')
if os.path.exists(__file__):
#
# Setup something resembling a normal environment and go.
#
sys.argv[0] = __file__
del argvemulator, os, sys, _dir
execfile(__file__)
#
# Setup something resembling a normal environment and go.
#
sys.argv[0] = __file__
del argvemulator, os, sys, _dir
execfile(__file__)
else:
__file__ = os.path.join(_dir, '__main__.pyc')
if os.path.exists(__file__):
#
# If we have only a .pyc file we read the code object from that
#
sys.argv[0] = __file__
_fp = open(__file__, 'rb')
_fp.read(8)
__code__ = marshal.load(_fp)
#
# Again, we create an almost-normal environment (only __code__ is
# funny) and go.
#
del argvemulator, os, sys, marshal, _dir, _fp
exec __code__
else:
sys.stderr.write("%s: neither __main__.py nor __main__.pyc found\n"%sys.argv[0])
sys.exit(1)
__file__ = os.path.join(_dir, '__main__.pyc')
if os.path.exists(__file__):
#
# If we have only a .pyc file we read the code object from that
#
sys.argv[0] = __file__
_fp = open(__file__, 'rb')
_fp.read(8)
__code__ = marshal.load(_fp)
#
# Again, we create an almost-normal environment (only __code__ is
# funny) and go.
#
del argvemulator, os, sys, marshal, _dir, _fp
exec __code__
else:
sys.stderr.write("%s: neither __main__.py nor __main__.pyc found\n"%sys.argv[0])
sys.exit(1)

View File

@ -6,12 +6,12 @@
import os
import sys
for name in ["__rawmain__.py", "__rawmain__.pyc", "__main__.py", "__main__.pyc"]:
realmain = os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])),
"Resources", name)
if os.path.exists(realmain):
break
realmain = os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])),
"Resources", name)
if os.path.exists(realmain):
break
else:
sys.stderr.write("%s: cannot find applet main program\n" % sys.argv[0])
sys.exit(1)
sys.stderr.write("%s: cannot find applet main program\n" % sys.argv[0])
sys.exit(1)
sys.argv.insert(1, realmain)
os.execve(sys.executable, sys.argv, os.environ)

View File

@ -12,12 +12,12 @@ Error = "bgenlocations.Error"
# Where bgen is. For unix-Python bgen isn't installed, so you have to refer to
# the source tree here.
if sys.platform == 'mac':
# For MacPython we know where it is
def _pardir(p): return os.path.split(p)[0]
BGENDIR=os.path.join(sys.prefix, "Tools", "bgen", "bgen")
# For MacPython we know where it is
def _pardir(p): return os.path.split(p)[0]
BGENDIR=os.path.join(sys.prefix, "Tools", "bgen", "bgen")
else:
# for unix-Python we don't know, please set it yourself.
BGENDIR="/Users/jack/src/python/Tools/bgen/bgen"
# for unix-Python we don't know, please set it yourself.
BGENDIR="/Users/jack/src/python/Tools/bgen/bgen"
#
# Where to find the Universal Header include files. If you have CodeWarrior
@ -26,9 +26,9 @@ else:
# end of lines, so don't worry about that.
#
if sys.platform == 'mac':
_MWERKSDIR="Sap:Applications (Mac OS 9):Metrowerks CodeWarrior 7.0:Metrowerks CodeWarrior"
_MWERKSDIR="Sap:Applications (Mac OS 9):Metrowerks CodeWarrior 7.0:Metrowerks CodeWarrior"
else:
_MWERKSDIR="/Volumes/Sap/Applications (Mac OS 9)/Metrowerks CodeWarrior 7.0/Metrowerks CodeWarrior/"
_MWERKSDIR="/Volumes/Sap/Applications (Mac OS 9)/Metrowerks CodeWarrior 7.0/Metrowerks CodeWarrior/"
INCLUDEDIR=os.path.join(_MWERKSDIR, "MacOS Support", "Universal", "Interfaces", "CIncludes")
#
@ -37,25 +37,25 @@ INCLUDEDIR=os.path.join(_MWERKSDIR, "MacOS Support", "Universal", "Interfaces",
# your source directory, not your installed directory.
#
if sys.platform == 'mac':
TOOLBOXDIR=os.path.join(sys.prefix, "Lib", "plat-mac", "Carbon")
TOOLBOXDIR=os.path.join(sys.prefix, "Lib", "plat-mac", "Carbon")
else:
TOOLBOXDIR="/Users/jack/src/python/Lib/plat-mac/Carbon"
TOOLBOXDIR="/Users/jack/src/python/Lib/plat-mac/Carbon"
# Creator for C files:
CREATOR="CWIE"
if not os.path.exists(BGENDIR):
raise Error, "Please fix bgenlocations.py, BGENDIR does not exist: %s" % BGENDIR
raise Error, "Please fix bgenlocations.py, BGENDIR does not exist: %s" % BGENDIR
if not os.path.exists(INCLUDEDIR):
raise Error, "Please fix bgenlocations.py, INCLUDEDIR does not exist: %s" % INCLUDEDIR
raise Error, "Please fix bgenlocations.py, INCLUDEDIR does not exist: %s" % INCLUDEDIR
if not os.path.exists(TOOLBOXDIR):
raise Error, "Please fix bgenlocations.py, TOOLBOXDIR does not exist: %s" % TOOLBOXDIR
raise Error, "Please fix bgenlocations.py, TOOLBOXDIR does not exist: %s" % TOOLBOXDIR
# Sigh, due to the way these are used make sure they end with : or /.
if BGENDIR[-1] != os.sep:
BGENDIR = BGENDIR + os.sep
BGENDIR = BGENDIR + os.sep
if INCLUDEDIR[-1] != os.sep:
INCLUDEDIR = INCLUDEDIR + os.sep
INCLUDEDIR = INCLUDEDIR + os.sep
if TOOLBOXDIR[-1] != os.sep:
TOOLBOXDIR = TOOLBOXDIR + os.sep
TOOLBOXDIR = TOOLBOXDIR + os.sep

View File

@ -42,375 +42,375 @@ WRITE = 2
RESOURCE_FORK_NAME=Carbon.File.FSGetResourceForkName()
def findtemplate(template=None):
"""Locate the applet template along sys.path"""
if MacOS.runtimemodel == 'macho':
return None
if not template:
template=TEMPLATE
for p in sys.path:
file = os.path.join(p, template)
try:
file, d1, d2 = Carbon.File.FSResolveAliasFile(file, 1)
break
except (Carbon.File.Error, ValueError):
continue
else:
raise BuildError, "Template %s not found on sys.path" % `template`
file = file.as_pathname()
return file
"""Locate the applet template along sys.path"""
if MacOS.runtimemodel == 'macho':
return None
if not template:
template=TEMPLATE
for p in sys.path:
file = os.path.join(p, template)
try:
file, d1, d2 = Carbon.File.FSResolveAliasFile(file, 1)
break
except (Carbon.File.Error, ValueError):
continue
else:
raise BuildError, "Template %s not found on sys.path" % `template`
file = file.as_pathname()
return file
def process(template, filename, destname, copy_codefragment=0,
rsrcname=None, others=[], raw=0, progress="default"):
if progress == "default":
progress = EasyDialogs.ProgressBar("Processing %s..."%os.path.split(filename)[1], 120)
progress.label("Compiling...")
progress.inc(0)
# check for the script name being longer than 32 chars. This may trigger a bug
# on OSX that can destroy your sourcefile.
if '#' in os.path.split(filename)[1]:
raise BuildError, "BuildApplet could destroy your sourcefile on OSX, please rename: %s" % filename
# Read the source and compile it
# (there's no point overwriting the destination if it has a syntax error)
fp = open(filename, 'rU')
text = fp.read()
fp.close()
try:
code = compile(text + '\n', filename, "exec")
except SyntaxError, arg:
raise BuildError, "Syntax error in script %s: %s" % (filename, arg)
except EOFError:
raise BuildError, "End-of-file in script %s" % (filename,)
# Set the destination file name. Note that basename
# does contain the whole filepath, only a .py is stripped.
if string.lower(filename[-3:]) == ".py":
basename = filename[:-3]
if MacOS.runtimemodel != 'macho' and not destname:
destname = basename
else:
basename = filename
if not destname:
if MacOS.runtimemodel == 'macho':
destname = basename + '.app'
else:
destname = basename + '.applet'
if not rsrcname:
rsrcname = basename + '.rsrc'
# Try removing the output file. This fails in MachO, but it should
# do any harm.
try:
os.remove(destname)
except os.error:
pass
process_common(template, progress, code, rsrcname, destname, 0,
copy_codefragment, raw, others, filename)
rsrcname=None, others=[], raw=0, progress="default"):
if progress == "default":
progress = EasyDialogs.ProgressBar("Processing %s..."%os.path.split(filename)[1], 120)
progress.label("Compiling...")
progress.inc(0)
# check for the script name being longer than 32 chars. This may trigger a bug
# on OSX that can destroy your sourcefile.
if '#' in os.path.split(filename)[1]:
raise BuildError, "BuildApplet could destroy your sourcefile on OSX, please rename: %s" % filename
# Read the source and compile it
# (there's no point overwriting the destination if it has a syntax error)
fp = open(filename, 'rU')
text = fp.read()
fp.close()
try:
code = compile(text + '\n', filename, "exec")
except SyntaxError, arg:
raise BuildError, "Syntax error in script %s: %s" % (filename, arg)
except EOFError:
raise BuildError, "End-of-file in script %s" % (filename,)
# Set the destination file name. Note that basename
# does contain the whole filepath, only a .py is stripped.
if string.lower(filename[-3:]) == ".py":
basename = filename[:-3]
if MacOS.runtimemodel != 'macho' and not destname:
destname = basename
else:
basename = filename
if not destname:
if MacOS.runtimemodel == 'macho':
destname = basename + '.app'
else:
destname = basename + '.applet'
if not rsrcname:
rsrcname = basename + '.rsrc'
# Try removing the output file. This fails in MachO, but it should
# do any harm.
try:
os.remove(destname)
except os.error:
pass
process_common(template, progress, code, rsrcname, destname, 0,
copy_codefragment, raw, others, filename)
def update(template, filename, output):
if MacOS.runtimemodel == 'macho':
raise BuildError, "No updating yet for MachO applets"
if progress:
progress = EasyDialogs.ProgressBar("Updating %s..."%os.path.split(filename)[1], 120)
else:
progress = None
if not output:
output = filename + ' (updated)'
# Try removing the output file
try:
os.remove(output)
except os.error:
pass
process_common(template, progress, None, filename, output, 1, 1)
if MacOS.runtimemodel == 'macho':
raise BuildError, "No updating yet for MachO applets"
if progress:
progress = EasyDialogs.ProgressBar("Updating %s..."%os.path.split(filename)[1], 120)
else:
progress = None
if not output:
output = filename + ' (updated)'
# Try removing the output file
try:
os.remove(output)
except os.error:
pass
process_common(template, progress, None, filename, output, 1, 1)
def process_common(template, progress, code, rsrcname, destname, is_update,
copy_codefragment, raw=0, others=[], filename=None):
if MacOS.runtimemodel == 'macho':
return process_common_macho(template, progress, code, rsrcname, destname,
is_update, raw, others, filename)
if others:
raise BuildError, "Extra files only allowed for MachoPython applets"
# Create FSSpecs for the various files
template_fsr, d1, d2 = Carbon.File.FSResolveAliasFile(template, 1)
template = template_fsr.as_pathname()
# Copy data (not resources, yet) from the template
if progress:
progress.label("Copy data fork...")
progress.set(10)
if copy_codefragment:
tmpl = open(template, "rb")
dest = open(destname, "wb")
data = tmpl.read()
if data:
dest.write(data)
dest.close()
tmpl.close()
del dest
del tmpl
# Open the output resource fork
if progress:
progress.label("Copy resources...")
progress.set(20)
try:
output = Res.FSOpenResourceFile(destname, RESOURCE_FORK_NAME, WRITE)
except MacOS.Error:
destdir, destfile = os.path.split(destname)
Res.FSCreateResourceFile(destdir, unicode(destfile), RESOURCE_FORK_NAME)
output = Res.FSOpenResourceFile(destname, RESOURCE_FORK_NAME, WRITE)
# Copy the resources from the target specific resource template, if any
typesfound, ownertype = [], None
try:
input = Res.FSOpenResourceFile(rsrcname, RESOURCE_FORK_NAME, READ)
except (MacOS.Error, ValueError):
pass
if progress:
progress.inc(50)
else:
if is_update:
skip_oldfile = ['cfrg']
else:
skip_oldfile = []
typesfound, ownertype = copyres(input, output, skip_oldfile, 0, progress)
Res.CloseResFile(input)
# Check which resource-types we should not copy from the template
skiptypes = []
if 'vers' in typesfound: skiptypes.append('vers')
if 'SIZE' in typesfound: skiptypes.append('SIZE')
if 'BNDL' in typesfound: skiptypes = skiptypes + ['BNDL', 'FREF', 'icl4',
'icl8', 'ics4', 'ics8', 'ICN#', 'ics#']
if not copy_codefragment:
skiptypes.append('cfrg')
## skipowner = (ownertype <> None)
# Copy the resources from the template
input = Res.FSOpenResourceFile(template, RESOURCE_FORK_NAME, READ)
dummy, tmplowner = copyres(input, output, skiptypes, 1, progress)
Res.CloseResFile(input)
## if ownertype == None:
## raise BuildError, "No owner resource found in either resource file or template"
# Make sure we're manipulating the output resource file now
Res.UseResFile(output)
copy_codefragment, raw=0, others=[], filename=None):
if MacOS.runtimemodel == 'macho':
return process_common_macho(template, progress, code, rsrcname, destname,
is_update, raw, others, filename)
if others:
raise BuildError, "Extra files only allowed for MachoPython applets"
# Create FSSpecs for the various files
template_fsr, d1, d2 = Carbon.File.FSResolveAliasFile(template, 1)
template = template_fsr.as_pathname()
# Copy data (not resources, yet) from the template
if progress:
progress.label("Copy data fork...")
progress.set(10)
if copy_codefragment:
tmpl = open(template, "rb")
dest = open(destname, "wb")
data = tmpl.read()
if data:
dest.write(data)
dest.close()
tmpl.close()
del dest
del tmpl
# Open the output resource fork
if progress:
progress.label("Copy resources...")
progress.set(20)
try:
output = Res.FSOpenResourceFile(destname, RESOURCE_FORK_NAME, WRITE)
except MacOS.Error:
destdir, destfile = os.path.split(destname)
Res.FSCreateResourceFile(destdir, unicode(destfile), RESOURCE_FORK_NAME)
output = Res.FSOpenResourceFile(destname, RESOURCE_FORK_NAME, WRITE)
# Copy the resources from the target specific resource template, if any
typesfound, ownertype = [], None
try:
input = Res.FSOpenResourceFile(rsrcname, RESOURCE_FORK_NAME, READ)
except (MacOS.Error, ValueError):
pass
if progress:
progress.inc(50)
else:
if is_update:
skip_oldfile = ['cfrg']
else:
skip_oldfile = []
typesfound, ownertype = copyres(input, output, skip_oldfile, 0, progress)
Res.CloseResFile(input)
# Check which resource-types we should not copy from the template
skiptypes = []
if 'vers' in typesfound: skiptypes.append('vers')
if 'SIZE' in typesfound: skiptypes.append('SIZE')
if 'BNDL' in typesfound: skiptypes = skiptypes + ['BNDL', 'FREF', 'icl4',
'icl8', 'ics4', 'ics8', 'ICN#', 'ics#']
if not copy_codefragment:
skiptypes.append('cfrg')
## skipowner = (ownertype <> None)
# Copy the resources from the template
input = Res.FSOpenResourceFile(template, RESOURCE_FORK_NAME, READ)
dummy, tmplowner = copyres(input, output, skiptypes, 1, progress)
Res.CloseResFile(input)
## if ownertype == None:
## raise BuildError, "No owner resource found in either resource file or template"
# Make sure we're manipulating the output resource file now
Res.UseResFile(output)
if ownertype == None:
# No owner resource in the template. We have skipped the
# Python owner resource, so we have to add our own. The relevant
# bundle stuff is already included in the interpret/applet template.
newres = Res.Resource('\0')
newres.AddResource(DEFAULT_APPLET_CREATOR, 0, "Owner resource")
ownertype = DEFAULT_APPLET_CREATOR
if code:
# Delete any existing 'PYC ' resource named __main__
try:
res = Res.Get1NamedResource(RESTYPE, RESNAME)
res.RemoveResource()
except Res.Error:
pass
# Create the raw data for the resource from the code object
if progress:
progress.label("Write PYC resource...")
progress.set(120)
data = marshal.dumps(code)
del code
data = (MAGIC + '\0\0\0\0') + data
# Create the resource and write it
id = 0
while id < 128:
id = Res.Unique1ID(RESTYPE)
res = Res.Resource(data)
res.AddResource(RESTYPE, id, RESNAME)
attrs = res.GetResAttrs()
attrs = attrs | 0x04 # set preload
res.SetResAttrs(attrs)
res.WriteResource()
res.ReleaseResource()
# Close the output file
Res.CloseResFile(output)
# Now set the creator, type and bundle bit of the destination.
# Done with FSSpec's, FSRef FInfo isn't good enough yet (2.3a1+)
dest_fss = Carbon.File.FSSpec(destname)
dest_finfo = dest_fss.FSpGetFInfo()
dest_finfo.Creator = ownertype
dest_finfo.Type = 'APPL'
dest_finfo.Flags = dest_finfo.Flags | Carbon.Files.kHasBundle | Carbon.Files.kIsShared
dest_finfo.Flags = dest_finfo.Flags & ~Carbon.Files.kHasBeenInited
dest_fss.FSpSetFInfo(dest_finfo)
macostools.touched(destname)
if progress:
progress.label("Done.")
progress.inc(0)
if ownertype == None:
# No owner resource in the template. We have skipped the
# Python owner resource, so we have to add our own. The relevant
# bundle stuff is already included in the interpret/applet template.
newres = Res.Resource('\0')
newres.AddResource(DEFAULT_APPLET_CREATOR, 0, "Owner resource")
ownertype = DEFAULT_APPLET_CREATOR
if code:
# Delete any existing 'PYC ' resource named __main__
try:
res = Res.Get1NamedResource(RESTYPE, RESNAME)
res.RemoveResource()
except Res.Error:
pass
# Create the raw data for the resource from the code object
if progress:
progress.label("Write PYC resource...")
progress.set(120)
data = marshal.dumps(code)
del code
data = (MAGIC + '\0\0\0\0') + data
# Create the resource and write it
id = 0
while id < 128:
id = Res.Unique1ID(RESTYPE)
res = Res.Resource(data)
res.AddResource(RESTYPE, id, RESNAME)
attrs = res.GetResAttrs()
attrs = attrs | 0x04 # set preload
res.SetResAttrs(attrs)
res.WriteResource()
res.ReleaseResource()
# Close the output file
Res.CloseResFile(output)
# Now set the creator, type and bundle bit of the destination.
# Done with FSSpec's, FSRef FInfo isn't good enough yet (2.3a1+)
dest_fss = Carbon.File.FSSpec(destname)
dest_finfo = dest_fss.FSpGetFInfo()
dest_finfo.Creator = ownertype
dest_finfo.Type = 'APPL'
dest_finfo.Flags = dest_finfo.Flags | Carbon.Files.kHasBundle | Carbon.Files.kIsShared
dest_finfo.Flags = dest_finfo.Flags & ~Carbon.Files.kHasBeenInited
dest_fss.FSpSetFInfo(dest_finfo)
macostools.touched(destname)
if progress:
progress.label("Done.")
progress.inc(0)
def process_common_macho(template, progress, code, rsrcname, destname, is_update,
raw=0, others=[], filename=None):
# Check that we have a filename
if filename is None:
raise BuildError, "Need source filename on MacOSX"
# First make sure the name ends in ".app"
if destname[-4:] != '.app':
destname = destname + '.app'
# Now deduce the short name
destdir, shortname = os.path.split(destname)
if shortname[-4:] == '.app':
# Strip the .app suffix
shortname = shortname[:-4]
# And deduce the .plist and .icns names
plistname = None
icnsname = None
if rsrcname and rsrcname[-5:] == '.rsrc':
tmp = rsrcname[:-5]
plistname = tmp + '.plist'
if os.path.exists(plistname):
icnsname = tmp + '.icns'
if not os.path.exists(icnsname):
icnsname = None
else:
plistname = None
if not os.path.exists(rsrcname):
rsrcname = None
if progress:
progress.label('Creating bundle...')
import bundlebuilder
builder = bundlebuilder.AppBuilder(verbosity=0)
builder.mainprogram = filename
builder.builddir = destdir
builder.name = shortname
if rsrcname:
realrsrcname = macresource.resource_pathname(rsrcname)
builder.files.append((realrsrcname,
os.path.join('Contents/Resources', os.path.basename(rsrcname))))
for o in others:
if type(o) == str:
builder.resources.append(o)
else:
builder.files.append(o)
if plistname:
import plistlib
builder.plist = plistlib.Plist.fromFile(plistname)
if icnsname:
builder.iconfile = icnsname
if not raw:
builder.argv_emulation = 1
builder.setup()
builder.build()
if progress:
progress.label('Done.')
progress.inc(0)
## macostools.touched(dest_fss)
raw=0, others=[], filename=None):
# Check that we have a filename
if filename is None:
raise BuildError, "Need source filename on MacOSX"
# First make sure the name ends in ".app"
if destname[-4:] != '.app':
destname = destname + '.app'
# Now deduce the short name
destdir, shortname = os.path.split(destname)
if shortname[-4:] == '.app':
# Strip the .app suffix
shortname = shortname[:-4]
# And deduce the .plist and .icns names
plistname = None
icnsname = None
if rsrcname and rsrcname[-5:] == '.rsrc':
tmp = rsrcname[:-5]
plistname = tmp + '.plist'
if os.path.exists(plistname):
icnsname = tmp + '.icns'
if not os.path.exists(icnsname):
icnsname = None
else:
plistname = None
if not os.path.exists(rsrcname):
rsrcname = None
if progress:
progress.label('Creating bundle...')
import bundlebuilder
builder = bundlebuilder.AppBuilder(verbosity=0)
builder.mainprogram = filename
builder.builddir = destdir
builder.name = shortname
if rsrcname:
realrsrcname = macresource.resource_pathname(rsrcname)
builder.files.append((realrsrcname,
os.path.join('Contents/Resources', os.path.basename(rsrcname))))
for o in others:
if type(o) == str:
builder.resources.append(o)
else:
builder.files.append(o)
if plistname:
import plistlib
builder.plist = plistlib.Plist.fromFile(plistname)
if icnsname:
builder.iconfile = icnsname
if not raw:
builder.argv_emulation = 1
builder.setup()
builder.build()
if progress:
progress.label('Done.')
progress.inc(0)
## macostools.touched(dest_fss)
# Copy resources between two resource file descriptors.
# skip a resource named '__main__' or (if skipowner is set) with ID zero.
# Also skip resources with a type listed in skiptypes.
#
def copyres(input, output, skiptypes, skipowner, progress=None):
ctor = None
alltypes = []
Res.UseResFile(input)
ntypes = Res.Count1Types()
progress_type_inc = 50/ntypes
for itype in range(1, 1+ntypes):
type = Res.Get1IndType(itype)
if type in skiptypes:
continue
alltypes.append(type)
nresources = Res.Count1Resources(type)
progress_cur_inc = progress_type_inc/nresources
for ires in range(1, 1+nresources):
res = Res.Get1IndResource(type, ires)
id, type, name = res.GetResInfo()
lcname = string.lower(name)
ctor = None
alltypes = []
Res.UseResFile(input)
ntypes = Res.Count1Types()
progress_type_inc = 50/ntypes
for itype in range(1, 1+ntypes):
type = Res.Get1IndType(itype)
if type in skiptypes:
continue
alltypes.append(type)
nresources = Res.Count1Resources(type)
progress_cur_inc = progress_type_inc/nresources
for ires in range(1, 1+nresources):
res = Res.Get1IndResource(type, ires)
id, type, name = res.GetResInfo()
lcname = string.lower(name)
if lcname == OWNERNAME and id == 0:
if skipowner:
continue # Skip this one
else:
ctor = type
size = res.size
attrs = res.GetResAttrs()
if progress:
progress.label("Copy %s %d %s"%(type, id, name))
progress.inc(progress_cur_inc)
res.LoadResource()
res.DetachResource()
Res.UseResFile(output)
try:
res2 = Res.Get1Resource(type, id)
except MacOS.Error:
res2 = None
if res2:
if progress:
progress.label("Overwrite %s %d %s"%(type, id, name))
progress.inc(0)
res2.RemoveResource()
res.AddResource(type, id, name)
res.WriteResource()
attrs = attrs | res.GetResAttrs()
res.SetResAttrs(attrs)
Res.UseResFile(input)
return alltypes, ctor
if lcname == OWNERNAME and id == 0:
if skipowner:
continue # Skip this one
else:
ctor = type
size = res.size
attrs = res.GetResAttrs()
if progress:
progress.label("Copy %s %d %s"%(type, id, name))
progress.inc(progress_cur_inc)
res.LoadResource()
res.DetachResource()
Res.UseResFile(output)
try:
res2 = Res.Get1Resource(type, id)
except MacOS.Error:
res2 = None
if res2:
if progress:
progress.label("Overwrite %s %d %s"%(type, id, name))
progress.inc(0)
res2.RemoveResource()
res.AddResource(type, id, name)
res.WriteResource()
attrs = attrs | res.GetResAttrs()
res.SetResAttrs(attrs)
Res.UseResFile(input)
return alltypes, ctor
def copyapptree(srctree, dsttree, exceptlist=[], progress=None):
names = []
if os.path.exists(dsttree):
shutil.rmtree(dsttree)
os.mkdir(dsttree)
todo = os.listdir(srctree)
while todo:
this, todo = todo[0], todo[1:]
if this in exceptlist:
continue
thispath = os.path.join(srctree, this)
if os.path.isdir(thispath):
thiscontent = os.listdir(thispath)
for t in thiscontent:
todo.append(os.path.join(this, t))
names.append(this)
for this in names:
srcpath = os.path.join(srctree, this)
dstpath = os.path.join(dsttree, this)
if os.path.isdir(srcpath):
os.mkdir(dstpath)
elif os.path.islink(srcpath):
endpoint = os.readlink(srcpath)
os.symlink(endpoint, dstpath)
else:
if progress:
progress.label('Copy '+this)
progress.inc(0)
shutil.copy2(srcpath, dstpath)
names = []
if os.path.exists(dsttree):
shutil.rmtree(dsttree)
os.mkdir(dsttree)
todo = os.listdir(srctree)
while todo:
this, todo = todo[0], todo[1:]
if this in exceptlist:
continue
thispath = os.path.join(srctree, this)
if os.path.isdir(thispath):
thiscontent = os.listdir(thispath)
for t in thiscontent:
todo.append(os.path.join(this, t))
names.append(this)
for this in names:
srcpath = os.path.join(srctree, this)
dstpath = os.path.join(dsttree, this)
if os.path.isdir(srcpath):
os.mkdir(dstpath)
elif os.path.islink(srcpath):
endpoint = os.readlink(srcpath)
os.symlink(endpoint, dstpath)
else:
if progress:
progress.label('Copy '+this)
progress.inc(0)
shutil.copy2(srcpath, dstpath)
def writepycfile(codeobject, cfile):
import marshal
fc = open(cfile, 'wb')
fc.write('\0\0\0\0') # MAGIC placeholder, written later
fc.write('\0\0\0\0') # Timestap placeholder, not needed
marshal.dump(codeobject, fc)
fc.flush()
fc.seek(0, 0)
fc.write(MAGIC)
fc.close()
import marshal
fc = open(cfile, 'wb')
fc.write('\0\0\0\0') # MAGIC placeholder, written later
fc.write('\0\0\0\0') # Timestap placeholder, not needed
marshal.dump(codeobject, fc)
fc.flush()
fc.seek(0, 0)
fc.write(MAGIC)
fc.close()

File diff suppressed because it is too large Load Diff

View File

@ -18,167 +18,167 @@ error = "cfm.error"
BUFSIZE = 0x80000
def mergecfmfiles(srclist, dst, architecture = 'fat'):
"""Merge all files in srclist into a new file dst.
If architecture is given, only code fragments of that type will be used:
"pwpc" for PPC, "m68k" for cfm68k. This does not work for "classic"
68k code, since it does not use code fragments to begin with.
If architecture is None, all fragments will be used, enabling FAT binaries.
"""
srclist = list(srclist)
for i in range(len(srclist)):
srclist[i] = Carbon.File.pathname(srclist[i])
dst = Carbon.File.pathname(dst)
dstfile = open(dst, "wb")
rf = Res.FSpOpenResFile(dst, 3)
try:
dstcfrg = CfrgResource()
for src in srclist:
srccfrg = CfrgResource(src)
for frag in srccfrg.fragments:
if frag.architecture == 'pwpc' and architecture == 'm68k':
continue
if frag.architecture == 'm68k' and architecture == 'pwpc':
continue
dstcfrg.append(frag)
frag.copydata(dstfile)
cfrgres = Res.Resource(dstcfrg.build())
Res.UseResFile(rf)
cfrgres.AddResource('cfrg', 0, "")
finally:
dstfile.close()
rf = Res.CloseResFile(rf)
"""Merge all files in srclist into a new file dst.
If architecture is given, only code fragments of that type will be used:
"pwpc" for PPC, "m68k" for cfm68k. This does not work for "classic"
68k code, since it does not use code fragments to begin with.
If architecture is None, all fragments will be used, enabling FAT binaries.
"""
srclist = list(srclist)
for i in range(len(srclist)):
srclist[i] = Carbon.File.pathname(srclist[i])
dst = Carbon.File.pathname(dst)
dstfile = open(dst, "wb")
rf = Res.FSpOpenResFile(dst, 3)
try:
dstcfrg = CfrgResource()
for src in srclist:
srccfrg = CfrgResource(src)
for frag in srccfrg.fragments:
if frag.architecture == 'pwpc' and architecture == 'm68k':
continue
if frag.architecture == 'm68k' and architecture == 'pwpc':
continue
dstcfrg.append(frag)
frag.copydata(dstfile)
cfrgres = Res.Resource(dstcfrg.build())
Res.UseResFile(rf)
cfrgres.AddResource('cfrg', 0, "")
finally:
dstfile.close()
rf = Res.CloseResFile(rf)
class CfrgResource:
def __init__(self, path = None):
self.version = 1
self.fragments = []
self.path = path
if path is not None and os.path.exists(path):
currentresref = Res.CurResFile()
resref = Res.FSpOpenResFile(path, 1)
Res.UseResFile(resref)
try:
try:
data = Res.Get1Resource('cfrg', 0).data
except Res.Error:
raise Res.Error, "no 'cfrg' resource found", sys.exc_traceback
finally:
Res.CloseResFile(resref)
Res.UseResFile(currentresref)
self.parse(data)
if self.version <> 1:
raise error, "unknown 'cfrg' resource format"
def parse(self, data):
(res1, res2, self.version,
res3, res4, res5, res6,
self.memberCount) = struct.unpack("8l", data[:32])
data = data[32:]
while data:
frag = FragmentDescriptor(self.path, data)
data = data[frag.memberSize:]
self.fragments.append(frag)
def build(self):
self.memberCount = len(self.fragments)
data = struct.pack("8l", 0, 0, self.version, 0, 0, 0, 0, self.memberCount)
for frag in self.fragments:
data = data + frag.build()
return data
def append(self, frag):
self.fragments.append(frag)
def __init__(self, path = None):
self.version = 1
self.fragments = []
self.path = path
if path is not None and os.path.exists(path):
currentresref = Res.CurResFile()
resref = Res.FSpOpenResFile(path, 1)
Res.UseResFile(resref)
try:
try:
data = Res.Get1Resource('cfrg', 0).data
except Res.Error:
raise Res.Error, "no 'cfrg' resource found", sys.exc_traceback
finally:
Res.CloseResFile(resref)
Res.UseResFile(currentresref)
self.parse(data)
if self.version <> 1:
raise error, "unknown 'cfrg' resource format"
def parse(self, data):
(res1, res2, self.version,
res3, res4, res5, res6,
self.memberCount) = struct.unpack("8l", data[:32])
data = data[32:]
while data:
frag = FragmentDescriptor(self.path, data)
data = data[frag.memberSize:]
self.fragments.append(frag)
def build(self):
self.memberCount = len(self.fragments)
data = struct.pack("8l", 0, 0, self.version, 0, 0, 0, 0, self.memberCount)
for frag in self.fragments:
data = data + frag.build()
return data
def append(self, frag):
self.fragments.append(frag)
class FragmentDescriptor:
def __init__(self, path, data = None):
self.path = path
if data is not None:
self.parse(data)
def parse(self, data):
self.architecture = data[:4]
( self.updatelevel,
self.currentVersion,
self.oldDefVersion,
self.stacksize,
self.applibdir,
self.fragtype,
self.where,
self.offset,
self.length,
self.res1, self.res2,
self.memberSize,) = struct.unpack("4lhBB4lh", data[4:42])
pname = data[42:self.memberSize]
self.name = pname[1:1+ord(pname[0])]
def build(self):
data = self.architecture
data = data + struct.pack("4lhBB4l",
self.updatelevel,
self.currentVersion,
self.oldDefVersion,
self.stacksize,
self.applibdir,
self.fragtype,
self.where,
self.offset,
self.length,
self.res1, self.res2)
self.memberSize = len(data) + 2 + 1 + len(self.name)
# pad to 4 byte boundaries
if self.memberSize % 4:
self.memberSize = self.memberSize + 4 - (self.memberSize % 4)
data = data + struct.pack("hb", self.memberSize, len(self.name))
data = data + self.name
data = data + '\000' * (self.memberSize - len(data))
return data
def getfragment(self):
if self.where <> 1:
raise error, "can't read fragment, unsupported location"
f = open(self.path, "rb")
f.seek(self.offset)
if self.length:
frag = f.read(self.length)
else:
frag = f.read()
f.close()
return frag
def copydata(self, outfile):
if self.where <> 1:
raise error, "can't read fragment, unsupported location"
infile = open(self.path, "rb")
if self.length == 0:
infile.seek(0, 2)
self.length = infile.tell()
# Position input file and record new offset from output file
infile.seek(self.offset)
# pad to 16 byte boundaries
offset = outfile.tell()
if offset % 16:
offset = offset + 16 - (offset % 16)
outfile.seek(offset)
self.offset = offset
l = self.length
while l:
if l > BUFSIZE:
outfile.write(infile.read(BUFSIZE))
l = l - BUFSIZE
else:
outfile.write(infile.read(l))
l = 0
infile.close()
def __init__(self, path, data = None):
self.path = path
if data is not None:
self.parse(data)
def parse(self, data):
self.architecture = data[:4]
( self.updatelevel,
self.currentVersion,
self.oldDefVersion,
self.stacksize,
self.applibdir,
self.fragtype,
self.where,
self.offset,
self.length,
self.res1, self.res2,
self.memberSize,) = struct.unpack("4lhBB4lh", data[4:42])
pname = data[42:self.memberSize]
self.name = pname[1:1+ord(pname[0])]
def build(self):
data = self.architecture
data = data + struct.pack("4lhBB4l",
self.updatelevel,
self.currentVersion,
self.oldDefVersion,
self.stacksize,
self.applibdir,
self.fragtype,
self.where,
self.offset,
self.length,
self.res1, self.res2)
self.memberSize = len(data) + 2 + 1 + len(self.name)
# pad to 4 byte boundaries
if self.memberSize % 4:
self.memberSize = self.memberSize + 4 - (self.memberSize % 4)
data = data + struct.pack("hb", self.memberSize, len(self.name))
data = data + self.name
data = data + '\000' * (self.memberSize - len(data))
return data
def getfragment(self):
if self.where <> 1:
raise error, "can't read fragment, unsupported location"
f = open(self.path, "rb")
f.seek(self.offset)
if self.length:
frag = f.read(self.length)
else:
frag = f.read()
f.close()
return frag
def copydata(self, outfile):
if self.where <> 1:
raise error, "can't read fragment, unsupported location"
infile = open(self.path, "rb")
if self.length == 0:
infile.seek(0, 2)
self.length = infile.tell()
# Position input file and record new offset from output file
infile.seek(self.offset)
# pad to 16 byte boundaries
offset = outfile.tell()
if offset % 16:
offset = offset + 16 - (offset % 16)
outfile.seek(offset)
self.offset = offset
l = self.length
while l:
if l > BUFSIZE:
outfile.write(infile.read(BUFSIZE))
l = l - BUFSIZE
else:
outfile.write(infile.read(l))
l = 0
infile.close()

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -11,16 +11,16 @@ import macostools
error=icglue.error
# From ictypes.h:
icPrefNotFoundErr = -666 # preference not found (duh!)
icPermErr = -667 # cannot set preference
icPrefDataErr = -668 # problem with preference data
icInternalErr = -669 # hmm, this is not good
icTruncatedErr = -670 # more data was present than was returned
icNoMoreWritersErr = -671 # you cannot begin a write session because someone else is already doing it */
icNothingToOverrideErr = -672 # no component for the override component to capture
icNoURLErr = -673 # no URL found
icConfigNotFoundErr = -674 # no configuration was found
icConfigInappropriateErr = -675 # incorrect manufacturer code
icPrefNotFoundErr = -666 # preference not found (duh!)
icPermErr = -667 # cannot set preference
icPrefDataErr = -668 # problem with preference data
icInternalErr = -669 # hmm, this is not good
icTruncatedErr = -670 # more data was present than was returned
icNoMoreWritersErr = -671 # you cannot begin a write session because someone else is already doing it */
icNothingToOverrideErr = -672 # no component for the override component to capture
icNoURLErr = -673 # no URL found
icConfigNotFoundErr = -674 # no configuration was found
icConfigInappropriateErr = -675 # incorrect manufacturer code
ICattr_no_change = -1
@ -30,240 +30,240 @@ icReadWritePerm = 2
# End of ictypes.h
class ICOpaqueData:
"""An unparseable IC entry"""
def __init__(self, data):
self.data = data
"""An unparseable IC entry"""
def __init__(self, data):
self.data = data
def __repr__(self):
return "ICOpaqueData(%s)"%`self.data`
def __repr__(self):
return "ICOpaqueData(%s)"%`self.data`
_ICOpaqueDataType=type(ICOpaqueData(''))
def _decode_default(data, key):
if len(data) == 0:
return data
if ord(data[0]) == len(data)-1:
# Assume Pstring
return data[1:]
return ICOpaqueData(data)
if len(data) == 0:
return data
if ord(data[0]) == len(data)-1:
# Assume Pstring
return data[1:]
return ICOpaqueData(data)
def _decode_multistr(data, key):
numstr = ord(data[0]) << 8 | ord(data[1])
rv = []
ptr = 2
for i in range(numstr):
strlen = ord(data[ptr])
str = data[ptr+1:ptr+strlen+1]
rv.append(str)
ptr = ptr + strlen + 1
return rv
numstr = ord(data[0]) << 8 | ord(data[1])
rv = []
ptr = 2
for i in range(numstr):
strlen = ord(data[ptr])
str = data[ptr+1:ptr+strlen+1]
rv.append(str)
ptr = ptr + strlen + 1
return rv
def _decode_fontrecord(data, key):
size = ord(data[0]) << 8 | ord(data[1])
face = ord(data[2])
namelen = ord(data[4])
return size, face, data[5:5+namelen]
size = ord(data[0]) << 8 | ord(data[1])
face = ord(data[2])
namelen = ord(data[4])
return size, face, data[5:5+namelen]
def _decode_boolean(data, key):
return ord(data[0])
return ord(data[0])
def _decode_text(data, key):
return data
return data
def _decode_charset(data, key):
return data[:256], data[256:]
return data[:256], data[256:]
def _decode_appspec(data, key):
namelen = ord(data[4])
return data[0:4], data[5:5+namelen]
namelen = ord(data[4])
return data[0:4], data[5:5+namelen]
def _code_default(data, key):
return chr(len(data)) + data
return chr(len(data)) + data
def _code_multistr(data, key):
numstr = len(data)
rv = chr((numstr>>8) & 0xff) + chr(numstr & 0xff)
for i in data:
rv = rv + _code_default(i)
return rv
numstr = len(data)
rv = chr((numstr>>8) & 0xff) + chr(numstr & 0xff)
for i in data:
rv = rv + _code_default(i)
return rv
def _code_fontrecord(data, key):
size, face, name = data
return chr((size>>8) & 0xff) + chr(size & 0xff) + chr(face & 0xff) + \
chr(0) + _code_default(name)
size, face, name = data
return chr((size>>8) & 0xff) + chr(size & 0xff) + chr(face & 0xff) + \
chr(0) + _code_default(name)
def _code_boolean(data, key):
print 'XXXX boolean:', `data`
return chr(data)
print 'XXXX boolean:', `data`
return chr(data)
def _code_text(data, key):
return data
return data
def _code_charset(data, key):
return data[0] + data[1]
return data[0] + data[1]
def _code_appspec(data, key):
return data[0] + _code_default(data[1])
return data[0] + _code_default(data[1])
_decoder_table = {
"ArchieAll" : (_decode_multistr , _code_multistr),
"UMichAll" : (_decode_multistr , _code_multistr),
"InfoMacAll" : (_decode_multistr , _code_multistr),
"ListFont" : (_decode_fontrecord , _code_fontrecord),
"ScreenFont" : (_decode_fontrecord , _code_fontrecord),
"PrinterFont" : (_decode_fontrecord , _code_fontrecord),
# "DownloadFolder" : (_decode_filespec , _code_filespec),
"Signature": (_decode_text , _code_text),
"Plan" : (_decode_text , _code_text),
"MailHeaders" : (_decode_text , _code_text),
"NewsHeaders" : (_decode_text , _code_text),
# "Mapping"
"CharacterSet" : (_decode_charset , _code_charset),
"Helper\245" : (_decode_appspec , _code_appspec),
# "Services" : (_decode_services, ????),
"NewMailFlashIcon" : (_decode_boolean , _code_boolean),
"NewMailDialog" : (_decode_boolean , _code_boolean),
"NewMailPlaySound" : (_decode_boolean , _code_boolean),
# "WebBackgroundColor" : _decode_color,
"NoProxyDomains" : (_decode_multistr , _code_multistr),
"UseHTTPProxy" : (_decode_boolean , _code_boolean),
"UseGopherProxy": (_decode_boolean , _code_boolean),
"UseFTPProxy" : (_decode_boolean , _code_boolean),
"UsePassiveFTP" : (_decode_boolean , _code_boolean),
"ArchieAll" : (_decode_multistr , _code_multistr),
"UMichAll" : (_decode_multistr , _code_multistr),
"InfoMacAll" : (_decode_multistr , _code_multistr),
"ListFont" : (_decode_fontrecord , _code_fontrecord),
"ScreenFont" : (_decode_fontrecord , _code_fontrecord),
"PrinterFont" : (_decode_fontrecord , _code_fontrecord),
# "DownloadFolder" : (_decode_filespec , _code_filespec),
"Signature": (_decode_text , _code_text),
"Plan" : (_decode_text , _code_text),
"MailHeaders" : (_decode_text , _code_text),
"NewsHeaders" : (_decode_text , _code_text),
# "Mapping"
"CharacterSet" : (_decode_charset , _code_charset),
"Helper\245" : (_decode_appspec , _code_appspec),
# "Services" : (_decode_services, ????),
"NewMailFlashIcon" : (_decode_boolean , _code_boolean),
"NewMailDialog" : (_decode_boolean , _code_boolean),
"NewMailPlaySound" : (_decode_boolean , _code_boolean),
# "WebBackgroundColor" : _decode_color,
"NoProxyDomains" : (_decode_multistr , _code_multistr),
"UseHTTPProxy" : (_decode_boolean , _code_boolean),
"UseGopherProxy": (_decode_boolean , _code_boolean),
"UseFTPProxy" : (_decode_boolean , _code_boolean),
"UsePassiveFTP" : (_decode_boolean , _code_boolean),
}
def _decode(data, key):
if '\245' in key:
key2 = key[:string.index(key, '\245')+1]
else:
key2 = key
if _decoder_table.has_key(key2):
decoder = _decoder_table[key2][0]
else:
decoder = _decode_default
return decoder(data, key)
if '\245' in key:
key2 = key[:string.index(key, '\245')+1]
else:
key2 = key
if _decoder_table.has_key(key2):
decoder = _decoder_table[key2][0]
else:
decoder = _decode_default
return decoder(data, key)
def _code(data, key):
if type(data) == _ICOpaqueDataType:
return data.data
if '\245' in key:
key2 = key[:string.index(key, '\245')+1]
else:
key2 = key
if _decoder_table.has_key(key2):
coder = _decoder_table[key2][1]
else:
coder = _code_default
return coder(data, key)
if type(data) == _ICOpaqueDataType:
return data.data
if '\245' in key:
key2 = key[:string.index(key, '\245')+1]
else:
key2 = key
if _decoder_table.has_key(key2):
coder = _decoder_table[key2][1]
else:
coder = _code_default
return coder(data, key)
class IC:
def __init__(self, signature='Pyth', ic=None):
if ic:
self.ic = ic
else:
self.ic = icglue.ICStart(signature)
if hasattr(self.ic, 'ICFindConfigFile'):
self.ic.ICFindConfigFile()
self.h = Res.Resource('')
def keys(self):
rv = []
self.ic.ICBegin(icReadOnlyPerm)
num = self.ic.ICCountPref()
for i in range(num):
rv.append(self.ic.ICGetIndPref(i+1))
self.ic.ICEnd()
return rv
def has_key(self, key):
return self.__contains__(key)
def __contains__(self, key):
try:
dummy = self.ic.ICFindPrefHandle(key, self.h)
except icglue.error:
return 0
return 1
def __getitem__(self, key):
attr = self.ic.ICFindPrefHandle(key, self.h)
return _decode(self.h.data, key)
def __setitem__(self, key, value):
value = _code(value, key)
self.ic.ICSetPref(key, ICattr_no_change, value)
def launchurl(self, url, hint=""):
# Work around a bug in ICLaunchURL: file:/foo does
# not work but file:///foo does.
if url[:6] == 'file:/' and url[6] != '/':
url = 'file:///' + url[6:]
self.ic.ICLaunchURL(hint, url, 0, len(url))
def parseurl(self, data, start=None, end=None, hint=""):
if start == None:
selStart = 0
selEnd = len(data)
else:
selStart = selEnd = start
if end != None:
selEnd = end
selStart, selEnd = self.ic.ICParseURL(hint, data, selStart, selEnd, self.h)
return self.h.data, selStart, selEnd
def mapfile(self, file):
if type(file) != type(''):
file = file.as_tuple()[2]
return self.ic.ICMapFilename(file)
def maptypecreator(self, type, creator, filename=""):
return self.ic.ICMapTypeCreator(type, creator, filename)
def settypecreator(self, file):
file = Carbon.File.pathname(file)
record = self.mapfile(os.path.split(file)[1])
MacOS.SetCreatorAndType(file, record[2], record[1])
macostools.touched(fss)
def __init__(self, signature='Pyth', ic=None):
if ic:
self.ic = ic
else:
self.ic = icglue.ICStart(signature)
if hasattr(self.ic, 'ICFindConfigFile'):
self.ic.ICFindConfigFile()
self.h = Res.Resource('')
def keys(self):
rv = []
self.ic.ICBegin(icReadOnlyPerm)
num = self.ic.ICCountPref()
for i in range(num):
rv.append(self.ic.ICGetIndPref(i+1))
self.ic.ICEnd()
return rv
def has_key(self, key):
return self.__contains__(key)
def __contains__(self, key):
try:
dummy = self.ic.ICFindPrefHandle(key, self.h)
except icglue.error:
return 0
return 1
def __getitem__(self, key):
attr = self.ic.ICFindPrefHandle(key, self.h)
return _decode(self.h.data, key)
def __setitem__(self, key, value):
value = _code(value, key)
self.ic.ICSetPref(key, ICattr_no_change, value)
def launchurl(self, url, hint=""):
# Work around a bug in ICLaunchURL: file:/foo does
# not work but file:///foo does.
if url[:6] == 'file:/' and url[6] != '/':
url = 'file:///' + url[6:]
self.ic.ICLaunchURL(hint, url, 0, len(url))
def parseurl(self, data, start=None, end=None, hint=""):
if start == None:
selStart = 0
selEnd = len(data)
else:
selStart = selEnd = start
if end != None:
selEnd = end
selStart, selEnd = self.ic.ICParseURL(hint, data, selStart, selEnd, self.h)
return self.h.data, selStart, selEnd
def mapfile(self, file):
if type(file) != type(''):
file = file.as_tuple()[2]
return self.ic.ICMapFilename(file)
def maptypecreator(self, type, creator, filename=""):
return self.ic.ICMapTypeCreator(type, creator, filename)
def settypecreator(self, file):
file = Carbon.File.pathname(file)
record = self.mapfile(os.path.split(file)[1])
MacOS.SetCreatorAndType(file, record[2], record[1])
macostools.touched(fss)
# Convenience routines
_dft_ic = None
def launchurl(url, hint=""):
global _dft_ic
if _dft_ic == None: _dft_ic = IC()
return _dft_ic.launchurl(url, hint)
global _dft_ic
if _dft_ic == None: _dft_ic = IC()
return _dft_ic.launchurl(url, hint)
def parseurl(data, start=None, end=None, hint=""):
global _dft_ic
if _dft_ic == None: _dft_ic = IC()
return _dft_ic.parseurl(data, start, end, hint)
global _dft_ic
if _dft_ic == None: _dft_ic = IC()
return _dft_ic.parseurl(data, start, end, hint)
def mapfile(filename):
global _dft_ic
if _dft_ic == None: _dft_ic = IC()
return _dft_ic.mapfile(filename)
global _dft_ic
if _dft_ic == None: _dft_ic = IC()
return _dft_ic.mapfile(filename)
def maptypecreator(type, creator, filename=""):
global _dft_ic
if _dft_ic == None: _dft_ic = IC()
return _dft_ic.maptypecreator(type, creator, filename)
global _dft_ic
if _dft_ic == None: _dft_ic = IC()
return _dft_ic.maptypecreator(type, creator, filename)
def settypecreator(file):
global _dft_ic
if _dft_ic == None: _dft_ic = IC()
return _dft_ic.settypecreator(file)
global _dft_ic
if _dft_ic == None: _dft_ic = IC()
return _dft_ic.settypecreator(file)
def _test():
ic = IC()
for k in ic.keys():
try:
v = ic[k]
except error:
v = '????'
print k, '\t', v
sys.exit(1)
ic = IC()
for k in ic.keys():
try:
v = ic[k]
except error:
v = '????'
print k, '\t', v
sys.exit(1)
if __name__ == '__main__':
_test()
_test()

File diff suppressed because it is too large Load Diff

View File

@ -28,25 +28,25 @@ smAllScripts = -3
# Find the epoch conversion for file dates in a way that works on OS9 and OSX
import time
if time.gmtime(0)[0] == 1970:
_EPOCHCONVERT = -((1970-1904)*365 + 17) * (24*60*60) + 0x100000000L
def _utc2time(utc):
t = utc[1] + _EPOCHCONVERT
return int(t)
def _time2utc(t):
t = int(t) - _EPOCHCONVERT
if t < -0x7fffffff:
t = t + 0x10000000L
return (0, int(t), 0)
_EPOCHCONVERT = -((1970-1904)*365 + 17) * (24*60*60) + 0x100000000L
def _utc2time(utc):
t = utc[1] + _EPOCHCONVERT
return int(t)
def _time2utc(t):
t = int(t) - _EPOCHCONVERT
if t < -0x7fffffff:
t = t + 0x10000000L
return (0, int(t), 0)
else:
def _utc2time(utc):
t = utc[1]
if t < 0:
t = t + 0x100000000L
return t
def _time2utc(t):
if t > 0x7fffffff:
t = t - 0x100000000L
return (0, int(t), 0)
def _utc2time(utc):
t = utc[1]
if t < 0:
t = t + 0x100000000L
return t
def _time2utc(t):
if t > 0x7fffffff:
t = t - 0x100000000L
return (0, int(t), 0)
# The old name of the error object:
error = Carbon.File.Error
@ -56,60 +56,60 @@ error = Carbon.File.Error
# of the method names are subtly different.
#
class FSSpec(Carbon.File.FSSpec):
def as_fsref(self):
return FSRef(self)
def NewAlias(self, src=None):
return Alias(Carbon.File.NewAlias(src, self))
def GetCreatorType(self):
finfo = self.FSpGetFInfo()
return finfo.Creator, finfo.Type
def SetCreatorType(self, ctor, tp):
finfo = self.FSpGetFInfo()
finfo.Creator = ctor
finfo.Type = tp
self.FSpSetFInfo(finfo)
def GetFInfo(self):
return self.FSpGetFInfo()
def SetFInfo(self, info):
return self.FSpSetFInfo(info)
def GetDates(self):
catInfoFlags = kFSCatInfoCreateDate|kFSCatInfoContentMod|kFSCatInfoBackupDate
catinfo, d1, d2, d3 = FSRef(self).FSGetCatalogInfo(catInfoFlags)
cdate = catinfo.createDate
mdate = catinfo.contentModDate
bdate = catinfo.backupDate
return _utc2time(cdate), _utc2time(mdate), _utc2time(bdate)
def SetDates(self, cdate, mdate, bdate):
catInfoFlags = kFSCatInfoCreateDate|kFSCatInfoContentMod|kFSCatInfoBackupDate
catinfo = Carbon.File.FSCatalogInfo(
createDate = _time2utc(cdate),
contentModDate = _time2utc(mdate),
backupDate = _time2utc(bdate))
FSRef(self).FSSetCatalogInfo(catInfoFlags, catinfo)
def as_fsref(self):
return FSRef(self)
def NewAlias(self, src=None):
return Alias(Carbon.File.NewAlias(src, self))
def GetCreatorType(self):
finfo = self.FSpGetFInfo()
return finfo.Creator, finfo.Type
def SetCreatorType(self, ctor, tp):
finfo = self.FSpGetFInfo()
finfo.Creator = ctor
finfo.Type = tp
self.FSpSetFInfo(finfo)
def GetFInfo(self):
return self.FSpGetFInfo()
def SetFInfo(self, info):
return self.FSpSetFInfo(info)
def GetDates(self):
catInfoFlags = kFSCatInfoCreateDate|kFSCatInfoContentMod|kFSCatInfoBackupDate
catinfo, d1, d2, d3 = FSRef(self).FSGetCatalogInfo(catInfoFlags)
cdate = catinfo.createDate
mdate = catinfo.contentModDate
bdate = catinfo.backupDate
return _utc2time(cdate), _utc2time(mdate), _utc2time(bdate)
def SetDates(self, cdate, mdate, bdate):
catInfoFlags = kFSCatInfoCreateDate|kFSCatInfoContentMod|kFSCatInfoBackupDate
catinfo = Carbon.File.FSCatalogInfo(
createDate = _time2utc(cdate),
contentModDate = _time2utc(mdate),
backupDate = _time2utc(bdate))
FSRef(self).FSSetCatalogInfo(catInfoFlags, catinfo)
class FSRef(Carbon.File.FSRef):
def as_fsspec(self):
return FSSpec(self)
def as_fsspec(self):
return FSSpec(self)
class Alias(Carbon.File.Alias):
def GetInfo(self, index):
return self.GetAliasInfo(index)
def Update(self, *args):
pass # print "Alias.Update not yet implemented"
def Resolve(self, src=None):
fss, changed = self.ResolveAlias(src)
return FSSpec(fss), changed
def GetInfo(self, index):
return self.GetAliasInfo(index)
def Update(self, *args):
pass # print "Alias.Update not yet implemented"
def Resolve(self, src=None):
fss, changed = self.ResolveAlias(src)
return FSSpec(fss), changed
from Carbon.File import FInfo
# Backward-compatible type names:
@ -120,21 +120,21 @@ FInfoType = FInfo
# Global functions:
def ResolveAliasFile(fss, chain=1):
fss, isdir, isalias = Carbon.File.ResolveAliasFile(fss, chain)
return FSSpec(fss), isdir, isalias
fss, isdir, isalias = Carbon.File.ResolveAliasFile(fss, chain)
return FSSpec(fss), isdir, isalias
def RawFSSpec(data):
return FSSpec(rawdata=data)
return FSSpec(rawdata=data)
def RawAlias(data):
return Alias(rawdata=data)
return Alias(rawdata=data)
def FindApplication(*args):
raise NotImplementedError, "FindApplication no longer implemented"
raise NotImplementedError, "FindApplication no longer implemented"
def NewAliasMinimalFromFullPath(path):
return Alias(Carbon.File.NewAliasMinimalFromFullPath(path, '', ''))
return Alias(Carbon.File.NewAliasMinimalFromFullPath(path, '', ''))
# Another global function:
from Carbon.Folder import FindFolder
@ -145,54 +145,54 @@ from Carbon.Folder import FindFolder
_curfolder = None
def StandardGetFile(*typelist):
"""Ask for an input file, optionally specifying 4-char file types that are
allowable"""
return PromptGetFile('', *typelist)
"""Ask for an input file, optionally specifying 4-char file types that are
allowable"""
return PromptGetFile('', *typelist)
def PromptGetFile(prompt, *typelist):
"""Ask for an input file giving the user a prompt message. Optionally you can
specifying 4-char file types that are allowable"""
import EasyDialogs
warnings.warn("macfs.StandardGetFile and friends are deprecated, use EasyDialogs.AskFileForOpen",
"""Ask for an input file giving the user a prompt message. Optionally you can
specifying 4-char file types that are allowable"""
import EasyDialogs
warnings.warn("macfs.StandardGetFile and friends are deprecated, use EasyDialogs.AskFileForOpen",
DeprecationWarning, stacklevel=2)
if not typelist:
typelist = None
fss = EasyDialogs.AskFileForOpen(message=prompt, wanted=FSSpec,
typeList=typelist, defaultLocation=_handleSetFolder())
return fss, not fss is None
if not typelist:
typelist = None
fss = EasyDialogs.AskFileForOpen(message=prompt, wanted=FSSpec,
typeList=typelist, defaultLocation=_handleSetFolder())
return fss, not fss is None
def StandardPutFile(prompt, default=None):
"""Ask the user for an output file, with a prompt. Optionally you cn supply a
default output filename"""
import EasyDialogs
warnings.warn("macfs.StandardGetFile and friends are deprecated, use EasyDialogs.AskFileForOpen",
"""Ask the user for an output file, with a prompt. Optionally you cn supply a
default output filename"""
import EasyDialogs
warnings.warn("macfs.StandardGetFile and friends are deprecated, use EasyDialogs.AskFileForOpen",
DeprecationWarning, stacklevel=2)
fss = EasyDialogs.AskFileForSave(wanted=FSSpec, message=prompt,
savedFileName=default, defaultLocation=_handleSetFolder())
return fss, not fss is None
fss = EasyDialogs.AskFileForSave(wanted=FSSpec, message=prompt,
savedFileName=default, defaultLocation=_handleSetFolder())
return fss, not fss is None
def SetFolder(folder):
global _curfolder
warnings.warn("macfs.StandardGetFile and friends are deprecated, use EasyDialogs.AskFileForOpen",
global _curfolder
warnings.warn("macfs.StandardGetFile and friends are deprecated, use EasyDialogs.AskFileForOpen",
DeprecationWarning, stacklevel=2)
if _curfolder:
rv = FSSpec(_curfolder)
else:
rv = None
_curfolder = folder
return rv
if _curfolder:
rv = FSSpec(_curfolder)
else:
rv = None
_curfolder = folder
return rv
def _handleSetFolder():
global _curfolder
rv = _curfolder
_curfolder = None
return rv
global _curfolder
rv = _curfolder
_curfolder = None
return rv
def GetDirectory(prompt=None):
"""Ask the user to select a folder. Optionally you can give a prompt."""
import EasyDialogs
warnings.warn("macfs.StandardGetFile and friends are deprecated, use EasyDialogs.AskFileForOpen",
"""Ask the user to select a folder. Optionally you can give a prompt."""
import EasyDialogs
warnings.warn("macfs.StandardGetFile and friends are deprecated, use EasyDialogs.AskFileForOpen",
DeprecationWarning, stacklevel=2)
fss = EasyDialogs.AskFolder(message=prompt, wanted=FSSpec,
defaultLocation=_handleSetFolder())
return fss, not fss is None
fss = EasyDialogs.AskFolder(message=prompt, wanted=FSSpec,
defaultLocation=_handleSetFolder())
return fss, not fss is None

View File

@ -10,137 +10,137 @@ class ArgumentError(TypeError): pass
class ResourceFileNotFoundError(ImportError): pass
def need(restype, resid, filename=None, modname=None):
"""Open a resource file, if needed. restype and resid
are required parameters, and identify the resource for which to test. If it
is available we are done. If it is not available we look for a file filename
(default: modname with .rsrc appended) either in the same folder as
where modname was loaded from, or otherwise across sys.path.
Returns the refno of the resource file opened (or None)"""
"""Open a resource file, if needed. restype and resid
are required parameters, and identify the resource for which to test. If it
is available we are done. If it is not available we look for a file filename
(default: modname with .rsrc appended) either in the same folder as
where modname was loaded from, or otherwise across sys.path.
Returns the refno of the resource file opened (or None)"""
if modname is None and filename is None:
raise ArgumentError, "Either filename or modname argument (or both) must be given"
if type(resid) is type(1):
try:
h = Res.GetResource(restype, resid)
except Res.Error:
pass
else:
return None
else:
try:
h = Res.GetNamedResource(restype, resid)
except Res.Error:
pass
else:
return None
# Construct a filename if we don't have one
if not filename:
if '.' in modname:
filename = modname.split('.')[-1] + '.rsrc'
else:
filename = modname + '.rsrc'
# Now create a list of folders to search
searchdirs = []
if modname == '__main__':
# If we're main we look in the current directory
searchdirs = [os.curdir]
if sys.modules.has_key(modname):
mod = sys.modules[modname]
if hasattr(mod, '__file__'):
searchdirs = [os.path.dirname(mod.__file__)]
searchdirs.extend(sys.path)
# And look for the file
for dir in searchdirs:
pathname = os.path.join(dir, filename)
if os.path.exists(pathname):
break
else:
raise ResourceFileNotFoundError, filename
refno = open_pathname(pathname)
# And check that the resource exists now
if type(resid) is type(1):
h = Res.GetResource(restype, resid)
else:
h = Res.GetNamedResource(restype, resid)
return refno
if modname is None and filename is None:
raise ArgumentError, "Either filename or modname argument (or both) must be given"
if type(resid) is type(1):
try:
h = Res.GetResource(restype, resid)
except Res.Error:
pass
else:
return None
else:
try:
h = Res.GetNamedResource(restype, resid)
except Res.Error:
pass
else:
return None
# Construct a filename if we don't have one
if not filename:
if '.' in modname:
filename = modname.split('.')[-1] + '.rsrc'
else:
filename = modname + '.rsrc'
# Now create a list of folders to search
searchdirs = []
if modname == '__main__':
# If we're main we look in the current directory
searchdirs = [os.curdir]
if sys.modules.has_key(modname):
mod = sys.modules[modname]
if hasattr(mod, '__file__'):
searchdirs = [os.path.dirname(mod.__file__)]
searchdirs.extend(sys.path)
# And look for the file
for dir in searchdirs:
pathname = os.path.join(dir, filename)
if os.path.exists(pathname):
break
else:
raise ResourceFileNotFoundError, filename
refno = open_pathname(pathname)
# And check that the resource exists now
if type(resid) is type(1):
h = Res.GetResource(restype, resid)
else:
h = Res.GetNamedResource(restype, resid)
return refno
def open_pathname(pathname, verbose=0):
"""Open a resource file given by pathname, possibly decoding an
AppleSingle file"""
try:
refno = Res.FSpOpenResFile(pathname, 1)
except Res.Error, arg:
if arg[0] in (-37, -39):
# No resource fork. We may be on OSX, and this may be either
# a data-fork based resource file or a AppleSingle file
# from the CVS repository.
try:
refno = Res.FSOpenResourceFile(pathname, u'', 1)
except Res.Error, arg:
if arg[0] != -199:
# -199 is "bad resource map"
raise
else:
return refno
# Finally try decoding an AppleSingle file
pathname = _decode(pathname, verbose=verbose)
refno = Res.FSOpenResourceFile(pathname, u'', 1)
else:
raise
return refno
"""Open a resource file given by pathname, possibly decoding an
AppleSingle file"""
try:
refno = Res.FSpOpenResFile(pathname, 1)
except Res.Error, arg:
if arg[0] in (-37, -39):
# No resource fork. We may be on OSX, and this may be either
# a data-fork based resource file or a AppleSingle file
# from the CVS repository.
try:
refno = Res.FSOpenResourceFile(pathname, u'', 1)
except Res.Error, arg:
if arg[0] != -199:
# -199 is "bad resource map"
raise
else:
return refno
# Finally try decoding an AppleSingle file
pathname = _decode(pathname, verbose=verbose)
refno = Res.FSOpenResourceFile(pathname, u'', 1)
else:
raise
return refno
def resource_pathname(pathname, verbose=0):
"""Return the pathname for a resource file (either DF or RF based).
If the pathname given already refers to such a file simply return it,
otherwise first decode it."""
try:
refno = Res.FSpOpenResFile(pathname, 1)
Res.CloseResFile(refno)
except Res.Error, arg:
if arg[0] in (-37, -39):
# No resource fork. We may be on OSX, and this may be either
# a data-fork based resource file or a AppleSingle file
# from the CVS repository.
try:
refno = Res.FSOpenResourceFile(pathname, u'', 1)
except Res.Error, arg:
if arg[0] != -199:
# -199 is "bad resource map"
raise
else:
return refno
# Finally try decoding an AppleSingle file
pathname = _decode(pathname, verbose=verbose)
else:
raise
return pathname
"""Return the pathname for a resource file (either DF or RF based).
If the pathname given already refers to such a file simply return it,
otherwise first decode it."""
try:
refno = Res.FSpOpenResFile(pathname, 1)
Res.CloseResFile(refno)
except Res.Error, arg:
if arg[0] in (-37, -39):
# No resource fork. We may be on OSX, and this may be either
# a data-fork based resource file or a AppleSingle file
# from the CVS repository.
try:
refno = Res.FSOpenResourceFile(pathname, u'', 1)
except Res.Error, arg:
if arg[0] != -199:
# -199 is "bad resource map"
raise
else:
return refno
# Finally try decoding an AppleSingle file
pathname = _decode(pathname, verbose=verbose)
else:
raise
return pathname
def open_error_resource():
"""Open the resource file containing the error code to error message
mapping."""
need('Estr', 1, filename="errors.rsrc", modname=__name__)
"""Open the resource file containing the error code to error message
mapping."""
need('Estr', 1, filename="errors.rsrc", modname=__name__)
def _decode(pathname, verbose=0):
# Decode an AppleSingle resource file, return the new pathname.
newpathname = pathname + '.df.rsrc'
if os.path.exists(newpathname) and \
os.stat(newpathname).st_mtime >= os.stat(pathname).st_mtime:
return newpathname
if hasattr(os, 'access') and not \
os.access(os.path.dirname(pathname), os.W_OK|os.X_OK):
# The destination directory isn't writeable. Create the file in
# a temporary directory
import tempfile
fd, newpathname = tempfile.mkstemp(".rsrc")
if verbose:
print 'Decoding', pathname, 'to', newpathname
import applesingle
applesingle.decode(pathname, newpathname, resonly=1)
return newpathname
# Decode an AppleSingle resource file, return the new pathname.
newpathname = pathname + '.df.rsrc'
if os.path.exists(newpathname) and \
os.stat(newpathname).st_mtime >= os.stat(pathname).st_mtime:
return newpathname
if hasattr(os, 'access') and not \
os.access(os.path.dirname(pathname), os.W_OK|os.X_OK):
# The destination directory isn't writeable. Create the file in
# a temporary directory
import tempfile
fd, newpathname = tempfile.mkstemp(".rsrc")
if verbose:
print 'Decoding', pathname, 'to', newpathname
import applesingle
applesingle.decode(pathname, newpathname, resonly=1)
return newpathname

File diff suppressed because it is too large Load Diff

View File

@ -33,29 +33,29 @@ The <date> plist data has (limited) support through the Date class.
Generate Plist example:
pl = Plist(
aString="Doodah",
aList=["A", "B", 12, 32.1, [1, 2, 3]],
aFloat = 0.1,
anInt = 728,
aDict=Dict(
anotherString="<hello & hi there!>",
aUnicodeValue=u'M\xe4ssig, Ma\xdf',
aTrueValue=True,
aFalseValue=False,
),
someData = Data("<binary gunk>"),
someMoreData = Data("<lots of binary gunk>" * 10),
aDate = Date(time.mktime(time.gmtime())),
)
# unicode keys are possible, but a little awkward to use:
pl[u'\xc5benraa'] = "That was a unicode key."
pl.write(fileName)
pl = Plist(
aString="Doodah",
aList=["A", "B", 12, 32.1, [1, 2, 3]],
aFloat = 0.1,
anInt = 728,
aDict=Dict(
anotherString="<hello & hi there!>",
aUnicodeValue=u'M\xe4ssig, Ma\xdf',
aTrueValue=True,
aFalseValue=False,
),
someData = Data("<binary gunk>"),
someMoreData = Data("<lots of binary gunk>" * 10),
aDate = Date(time.mktime(time.gmtime())),
)
# unicode keys are possible, but a little awkward to use:
pl[u'\xc5benraa'] = "That was a unicode key."
pl.write(fileName)
Parse Plist example:
pl = Plist.fromFile(pathOrFile)
print pl.aKey
pl = Plist.fromFile(pathOrFile)
print pl.aKey
"""
@ -71,40 +71,40 @@ INDENT = "\t"
class DumbXMLWriter:
def __init__(self, file):
self.file = file
self.stack = []
self.indentLevel = 0
def __init__(self, file):
self.file = file
self.stack = []
self.indentLevel = 0
def beginElement(self, element):
self.stack.append(element)
self.writeln("<%s>" % element)
self.indentLevel += 1
def beginElement(self, element):
self.stack.append(element)
self.writeln("<%s>" % element)
self.indentLevel += 1
def endElement(self, element):
assert self.indentLevel > 0
assert self.stack.pop() == element
self.indentLevel -= 1
self.writeln("</%s>" % element)
def endElement(self, element):
assert self.indentLevel > 0
assert self.stack.pop() == element
self.indentLevel -= 1
self.writeln("</%s>" % element)
def simpleElement(self, element, value=None):
if value:
value = _encode(value)
self.writeln("<%s>%s</%s>" % (element, value, element))
else:
self.writeln("<%s/>" % element)
def simpleElement(self, element, value=None):
if value:
value = _encode(value)
self.writeln("<%s>%s</%s>" % (element, value, element))
else:
self.writeln("<%s/>" % element)
def writeln(self, line):
if line:
self.file.write(self.indentLevel * INDENT + line + "\n")
else:
self.file.write("\n")
def writeln(self, line):
if line:
self.file.write(self.indentLevel * INDENT + line + "\n")
else:
self.file.write("\n")
def _encode(text):
text = text.replace("&", "&amp;")
text = text.replace("<", "&lt;")
return text.encode("utf-8")
text = text.replace("&", "&amp;")
text = text.replace("<", "&lt;")
return text.encode("utf-8")
PLISTHEADER = """\
@ -114,323 +114,323 @@ PLISTHEADER = """\
class PlistWriter(DumbXMLWriter):
def __init__(self, file):
file.write(PLISTHEADER)
DumbXMLWriter.__init__(self, file)
def __init__(self, file):
file.write(PLISTHEADER)
DumbXMLWriter.__init__(self, file)
def writeValue(self, value):
if isinstance(value, (str, unicode)):
self.simpleElement("string", value)
elif isinstance(value, bool):
# must switch for bool before int, as bool is a
# subclass of int...
if value:
self.simpleElement("true")
else:
self.simpleElement("false")
elif isinstance(value, int):
self.simpleElement("integer", str(value))
elif isinstance(value, float):
# should perhaps use repr() for better precision?
self.simpleElement("real", str(value))
elif isinstance(value, (dict, Dict)):
self.writeDict(value)
elif isinstance(value, Data):
self.writeData(value)
elif isinstance(value, Date):
self.simpleElement("date", value.toString())
elif isinstance(value, (tuple, list)):
self.writeArray(value)
else:
assert 0, "unsuported type: %s" % type(value)
def writeValue(self, value):
if isinstance(value, (str, unicode)):
self.simpleElement("string", value)
elif isinstance(value, bool):
# must switch for bool before int, as bool is a
# subclass of int...
if value:
self.simpleElement("true")
else:
self.simpleElement("false")
elif isinstance(value, int):
self.simpleElement("integer", str(value))
elif isinstance(value, float):
# should perhaps use repr() for better precision?
self.simpleElement("real", str(value))
elif isinstance(value, (dict, Dict)):
self.writeDict(value)
elif isinstance(value, Data):
self.writeData(value)
elif isinstance(value, Date):
self.simpleElement("date", value.toString())
elif isinstance(value, (tuple, list)):
self.writeArray(value)
else:
assert 0, "unsuported type: %s" % type(value)
def writeData(self, data):
self.beginElement("data")
for line in data.asBase64().split("\n"):
if line:
self.writeln(line)
self.endElement("data")
def writeData(self, data):
self.beginElement("data")
for line in data.asBase64().split("\n"):
if line:
self.writeln(line)
self.endElement("data")
def writeDict(self, d):
self.beginElement("dict")
items = d.items()
items.sort()
for key, value in items:
assert isinstance(key, (str, unicode)), "keys must be strings"
self.simpleElement("key", key)
self.writeValue(value)
self.endElement("dict")
def writeDict(self, d):
self.beginElement("dict")
items = d.items()
items.sort()
for key, value in items:
assert isinstance(key, (str, unicode)), "keys must be strings"
self.simpleElement("key", key)
self.writeValue(value)
self.endElement("dict")
def writeArray(self, array):
self.beginElement("array")
for value in array:
self.writeValue(value)
self.endElement("array")
def writeArray(self, array):
self.beginElement("array")
for value in array:
self.writeValue(value)
self.endElement("array")
class Dict:
"""Dict wrapper for convenient access of values through attributes."""
"""Dict wrapper for convenient access of values through attributes."""
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __cmp__(self, other):
if isinstance(other, self.__class__):
return cmp(self.__dict__, other.__dict__)
elif isinstance(other, dict):
return cmp(self.__dict__, other)
else:
return cmp(id(self), id(other))
def __cmp__(self, other):
if isinstance(other, self.__class__):
return cmp(self.__dict__, other.__dict__)
elif isinstance(other, dict):
return cmp(self.__dict__, other)
else:
return cmp(id(self), id(other))
def __str__(self):
return "%s(**%s)" % (self.__class__.__name__, self.__dict__)
__repr__ = __str__
def __str__(self):
return "%s(**%s)" % (self.__class__.__name__, self.__dict__)
__repr__ = __str__
def copy(self):
return self.__class__(**self.__dict__)
def copy(self):
return self.__class__(**self.__dict__)
def __getattr__(self, attr):
"""Delegate everything else to the dict object."""
return getattr(self.__dict__, attr)
def __getattr__(self, attr):
"""Delegate everything else to the dict object."""
return getattr(self.__dict__, attr)
class Plist(Dict):
"""The main Plist object. Basically a dict (the toplevel object
of a plist is a dict) with two additional methods to read from
and write to files.
"""
"""The main Plist object. Basically a dict (the toplevel object
of a plist is a dict) with two additional methods to read from
and write to files.
"""
def fromFile(cls, pathOrFile):
didOpen = 0
if not hasattr(pathOrFile, "write"):
pathOrFile = open(pathOrFile)
didOpen = 1
p = PlistParser()
plist = p.parse(pathOrFile)
if didOpen:
pathOrFile.close()
return plist
fromFile = classmethod(fromFile)
def fromFile(cls, pathOrFile):
didOpen = 0
if not hasattr(pathOrFile, "write"):
pathOrFile = open(pathOrFile)
didOpen = 1
p = PlistParser()
plist = p.parse(pathOrFile)
if didOpen:
pathOrFile.close()
return plist
fromFile = classmethod(fromFile)
def write(self, pathOrFile):
if not hasattr(pathOrFile, "write"):
pathOrFile = open(pathOrFile, "w")
didOpen = 1
else:
didOpen = 0
def write(self, pathOrFile):
if not hasattr(pathOrFile, "write"):
pathOrFile = open(pathOrFile, "w")
didOpen = 1
else:
didOpen = 0
writer = PlistWriter(pathOrFile)
writer.writeln("<plist version=\"1.0\">")
writer.writeDict(self.__dict__)
writer.writeln("</plist>")
writer = PlistWriter(pathOrFile)
writer.writeln("<plist version=\"1.0\">")
writer.writeDict(self.__dict__)
writer.writeln("</plist>")
if didOpen:
pathOrFile.close()
if didOpen:
pathOrFile.close()
class Data:
"""Wrapper for binary data."""
"""Wrapper for binary data."""
def __init__(self, data):
self.data = data
def __init__(self, data):
self.data = data
def fromBase64(cls, data):
import base64
return cls(base64.decodestring(data))
fromBase64 = classmethod(fromBase64)
def fromBase64(cls, data):
import base64
return cls(base64.decodestring(data))
fromBase64 = classmethod(fromBase64)
def asBase64(self):
import base64
return base64.encodestring(self.data)
def asBase64(self):
import base64
return base64.encodestring(self.data)
def __cmp__(self, other):
if isinstance(other, self.__class__):
return cmp(self.data, other.data)
elif isinstance(other, str):
return cmp(self.data, other)
else:
return cmp(id(self), id(other))
def __cmp__(self, other):
if isinstance(other, self.__class__):
return cmp(self.data, other.data)
elif isinstance(other, str):
return cmp(self.data, other)
else:
return cmp(id(self), id(other))
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__, repr(self.data))
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__, repr(self.data))
class Date:
"""Primitive date wrapper, uses time floats internally, is agnostic
about time zones.
"""
"""Primitive date wrapper, uses time floats internally, is agnostic
about time zones.
"""
def __init__(self, date):
if isinstance(date, str):
from xml.utils.iso8601 import parse
date = parse(date)
self.date = date
def __init__(self, date):
if isinstance(date, str):
from xml.utils.iso8601 import parse
date = parse(date)
self.date = date
def toString(self):
from xml.utils.iso8601 import tostring
return tostring(self.date)
def toString(self):
from xml.utils.iso8601 import tostring
return tostring(self.date)
def __cmp__(self, other):
if isinstance(other, self.__class__):
return cmp(self.date, other.date)
elif isinstance(other, (int, float)):
return cmp(self.date, other)
else:
return cmp(id(self), id(other))
def __cmp__(self, other):
if isinstance(other, self.__class__):
return cmp(self.date, other.date)
elif isinstance(other, (int, float)):
return cmp(self.date, other)
else:
return cmp(id(self), id(other))
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__, repr(self.toString()))
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__, repr(self.toString()))
class PlistParser:
def __init__(self):
self.stack = []
self.currentKey = None
self.root = None
def __init__(self):
self.stack = []
self.currentKey = None
self.root = None
def parse(self, file):
from xml.parsers.expat import ParserCreate
parser = ParserCreate()
parser.StartElementHandler = self.handleBeginElement
parser.EndElementHandler = self.handleEndElement
parser.CharacterDataHandler = self.handleData
parser.ParseFile(file)
return self.root
def parse(self, file):
from xml.parsers.expat import ParserCreate
parser = ParserCreate()
parser.StartElementHandler = self.handleBeginElement
parser.EndElementHandler = self.handleEndElement
parser.CharacterDataHandler = self.handleData
parser.ParseFile(file)
return self.root
def handleBeginElement(self, element, attrs):
self.data = []
handler = getattr(self, "begin_" + element, None)
if handler is not None:
handler(attrs)
def handleBeginElement(self, element, attrs):
self.data = []
handler = getattr(self, "begin_" + element, None)
if handler is not None:
handler(attrs)
def handleEndElement(self, element):
handler = getattr(self, "end_" + element, None)
if handler is not None:
handler()
def handleEndElement(self, element):
handler = getattr(self, "end_" + element, None)
if handler is not None:
handler()
def handleData(self, data):
self.data.append(data)
def handleData(self, data):
self.data.append(data)
def addObject(self, value):
if self.currentKey is not None:
self.stack[-1][self.currentKey] = value
self.currentKey = None
elif not self.stack:
# this is the root object
assert self.root is value
else:
self.stack[-1].append(value)
def addObject(self, value):
if self.currentKey is not None:
self.stack[-1][self.currentKey] = value
self.currentKey = None
elif not self.stack:
# this is the root object
assert self.root is value
else:
self.stack[-1].append(value)
def getData(self):
data = "".join(self.data)
try:
data = data.encode("ascii")
except UnicodeError:
pass
self.data = []
return data
def getData(self):
data = "".join(self.data)
try:
data = data.encode("ascii")
except UnicodeError:
pass
self.data = []
return data
# element handlers
# element handlers
def begin_dict(self, attrs):
if self.root is None:
self.root = d = Plist()
else:
d = Dict()
self.addObject(d)
self.stack.append(d)
def end_dict(self):
self.stack.pop()
def begin_dict(self, attrs):
if self.root is None:
self.root = d = Plist()
else:
d = Dict()
self.addObject(d)
self.stack.append(d)
def end_dict(self):
self.stack.pop()
def end_key(self):
self.currentKey = self.getData()
def end_key(self):
self.currentKey = self.getData()
def begin_array(self, attrs):
a = []
self.addObject(a)
self.stack.append(a)
def end_array(self):
self.stack.pop()
def begin_array(self, attrs):
a = []
self.addObject(a)
self.stack.append(a)
def end_array(self):
self.stack.pop()
def end_true(self):
self.addObject(True)
def end_false(self):
self.addObject(False)
def end_integer(self):
self.addObject(int(self.getData()))
def end_real(self):
self.addObject(float(self.getData()))
def end_string(self):
self.addObject(self.getData())
def end_data(self):
self.addObject(Data.fromBase64(self.getData()))
def end_date(self):
self.addObject(Date(self.getData()))
def end_true(self):
self.addObject(True)
def end_false(self):
self.addObject(False)
def end_integer(self):
self.addObject(int(self.getData()))
def end_real(self):
self.addObject(float(self.getData()))
def end_string(self):
self.addObject(self.getData())
def end_data(self):
self.addObject(Data.fromBase64(self.getData()))
def end_date(self):
self.addObject(Date(self.getData()))
# cruft to support booleans in Python <= 2.3
import sys
if sys.version_info[:2] < (2, 3):
# Python 2.2 and earlier: no booleans
# Python 2.2.x: booleans are ints
class bool(int):
"""Imitation of the Python 2.3 bool object."""
def __new__(cls, value):
return int.__new__(cls, not not value)
def __repr__(self):
if self:
return "True"
else:
return "False"
True = bool(1)
False = bool(0)
# Python 2.2 and earlier: no booleans
# Python 2.2.x: booleans are ints
class bool(int):
"""Imitation of the Python 2.3 bool object."""
def __new__(cls, value):
return int.__new__(cls, not not value)
def __repr__(self):
if self:
return "True"
else:
return "False"
True = bool(1)
False = bool(0)
else:
# Bind the boolean builtins to local names
True = True
False = False
bool = bool
# Bind the boolean builtins to local names
True = True
False = False
bool = bool
if __name__ == "__main__":
from StringIO import StringIO
import time
if len(sys.argv) == 1:
pl = Plist(
aString="Doodah",
aList=["A", "B", 12, 32.1, [1, 2, 3]],
aFloat = 0.1,
anInt = 728,
aDict=Dict(
anotherString="<hello & hi there!>",
aUnicodeValue=u'M\xe4ssig, Ma\xdf',
aTrueValue=True,
aFalseValue=False,
),
someData = Data("<binary gunk>"),
someMoreData = Data("<lots of binary gunk>" * 10),
aDate = Date(time.mktime(time.gmtime())),
)
elif len(sys.argv) == 2:
pl = Plist.fromFile(sys.argv[1])
else:
print "Too many arguments: at most 1 plist file can be given."
sys.exit(1)
from StringIO import StringIO
import time
if len(sys.argv) == 1:
pl = Plist(
aString="Doodah",
aList=["A", "B", 12, 32.1, [1, 2, 3]],
aFloat = 0.1,
anInt = 728,
aDict=Dict(
anotherString="<hello & hi there!>",
aUnicodeValue=u'M\xe4ssig, Ma\xdf',
aTrueValue=True,
aFalseValue=False,
),
someData = Data("<binary gunk>"),
someMoreData = Data("<lots of binary gunk>" * 10),
aDate = Date(time.mktime(time.gmtime())),
)
elif len(sys.argv) == 2:
pl = Plist.fromFile(sys.argv[1])
else:
print "Too many arguments: at most 1 plist file can be given."
sys.exit(1)
# unicode keys are possible, but a little awkward to use:
pl[u'\xc5benraa'] = "That was a unicode key."
f = StringIO()
pl.write(f)
xml = f.getvalue()
print xml
f.seek(0)
pl2 = Plist.fromFile(f)
assert pl == pl2
f = StringIO()
pl2.write(f)
assert xml == f.getvalue()
#print repr(pl2)
# unicode keys are possible, but a little awkward to use:
pl[u'\xc5benraa'] = "That was a unicode key."
f = StringIO()
pl.write(f)
xml = f.getvalue()
print xml
f.seek(0)
pl2 = Plist.fromFile(f)
assert pl == pl2
f = StringIO()
pl2.write(f)
assert xml == f.getvalue()
#print repr(pl2)

View File

@ -13,280 +13,280 @@ from Carbon import Qdoffs
from Carbon import QDOffscreen
from Carbon import Res
try:
import MediaDescr
import MediaDescr
except ImportError:
def _audiodescr(data):
return None
def _audiodescr(data):
return None
else:
def _audiodescr(data):
return MediaDescr.SoundDescription.decode(data)
def _audiodescr(data):
return MediaDescr.SoundDescription.decode(data)
try:
from imgformat import macrgb
from imgformat import macrgb
except ImportError:
macrgb = "Macintosh RGB format"
macrgb = "Macintosh RGB format"
import os
# import audio.format
class VideoFormat:
def __init__(self, name, descr, width, height, format):
self.__name = name
self.__descr = descr
self.__width = width
self.__height = height
self.__format = format
def getname(self):
return self.__name
def getdescr(self):
return self.__descr
def getsize(self):
return self.__width, self.__height
def getformat(self):
return self.__format
def __init__(self, name, descr, width, height, format):
self.__name = name
self.__descr = descr
self.__width = width
self.__height = height
self.__format = format
def getname(self):
return self.__name
def getdescr(self):
return self.__descr
def getsize(self):
return self.__width, self.__height
def getformat(self):
return self.__format
class _Reader:
def __init__(self, path):
fd = Qt.OpenMovieFile(path, 0)
self.movie, d1, d2 = Qt.NewMovieFromFile(fd, 0, 0)
self.movietimescale = self.movie.GetMovieTimeScale()
try:
self.audiotrack = self.movie.GetMovieIndTrackType(1,
QuickTime.AudioMediaCharacteristic, QuickTime.movieTrackCharacteristic)
self.audiomedia = self.audiotrack.GetTrackMedia()
except Qt.Error:
self.audiotrack = self.audiomedia = None
self.audiodescr = {}
else:
handle = Res.Handle('')
n = self.audiomedia.GetMediaSampleDescriptionCount()
self.audiomedia.GetMediaSampleDescription(1, handle)
self.audiodescr = _audiodescr(handle.data)
self.audiotimescale = self.audiomedia.GetMediaTimeScale()
del handle
try:
self.videotrack = self.movie.GetMovieIndTrackType(1,
QuickTime.VisualMediaCharacteristic, QuickTime.movieTrackCharacteristic)
self.videomedia = self.videotrack.GetTrackMedia()
except Qt.Error:
self.videotrack = self.videomedia = self.videotimescale = None
if self.videotrack:
self.videotimescale = self.videomedia.GetMediaTimeScale()
x0, y0, x1, y1 = self.movie.GetMovieBox()
self.videodescr = {'width':(x1-x0), 'height':(y1-y0)}
self._initgworld()
self.videocurtime = None
self.audiocurtime = None
def __init__(self, path):
fd = Qt.OpenMovieFile(path, 0)
self.movie, d1, d2 = Qt.NewMovieFromFile(fd, 0, 0)
self.movietimescale = self.movie.GetMovieTimeScale()
try:
self.audiotrack = self.movie.GetMovieIndTrackType(1,
QuickTime.AudioMediaCharacteristic, QuickTime.movieTrackCharacteristic)
self.audiomedia = self.audiotrack.GetTrackMedia()
except Qt.Error:
self.audiotrack = self.audiomedia = None
self.audiodescr = {}
else:
handle = Res.Handle('')
n = self.audiomedia.GetMediaSampleDescriptionCount()
self.audiomedia.GetMediaSampleDescription(1, handle)
self.audiodescr = _audiodescr(handle.data)
self.audiotimescale = self.audiomedia.GetMediaTimeScale()
del handle
try:
self.videotrack = self.movie.GetMovieIndTrackType(1,
QuickTime.VisualMediaCharacteristic, QuickTime.movieTrackCharacteristic)
self.videomedia = self.videotrack.GetTrackMedia()
except Qt.Error:
self.videotrack = self.videomedia = self.videotimescale = None
if self.videotrack:
self.videotimescale = self.videomedia.GetMediaTimeScale()
x0, y0, x1, y1 = self.movie.GetMovieBox()
self.videodescr = {'width':(x1-x0), 'height':(y1-y0)}
self._initgworld()
self.videocurtime = None
self.audiocurtime = None
def __del__(self):
self.audiomedia = None
self.audiotrack = None
self.videomedia = None
self.videotrack = None
self.movie = None
def _initgworld(self):
old_port, old_dev = Qdoffs.GetGWorld()
try:
movie_w = self.videodescr['width']
movie_h = self.videodescr['height']
movie_rect = (0, 0, movie_w, movie_h)
self.gworld = Qdoffs.NewGWorld(32, movie_rect, None, None, QDOffscreen.keepLocal)
self.pixmap = self.gworld.GetGWorldPixMap()
Qdoffs.LockPixels(self.pixmap)
Qdoffs.SetGWorld(self.gworld.as_GrafPtr(), None)
Qd.EraseRect(movie_rect)
self.movie.SetMovieGWorld(self.gworld.as_GrafPtr(), None)
self.movie.SetMovieBox(movie_rect)
self.movie.SetMovieActive(1)
self.movie.MoviesTask(0)
self.movie.SetMoviePlayHints(QuickTime.hintsHighQuality, QuickTime.hintsHighQuality)
# XXXX framerate
finally:
Qdoffs.SetGWorld(old_port, old_dev)
def _gettrackduration_ms(self, track):
tracktime = track.GetTrackDuration()
return self._movietime_to_ms(tracktime)
def _movietime_to_ms(self, time):
value, d1, d2 = Qt.ConvertTimeScale((time, self.movietimescale, None), 1000)
return value
def _videotime_to_ms(self, time):
value, d1, d2 = Qt.ConvertTimeScale((time, self.videotimescale, None), 1000)
return value
def _audiotime_to_ms(self, time):
value, d1, d2 = Qt.ConvertTimeScale((time, self.audiotimescale, None), 1000)
return value
def _videotime_to_movietime(self, time):
value, d1, d2 = Qt.ConvertTimeScale((time, self.videotimescale, None),
self.movietimescale)
return value
def HasAudio(self):
return not self.audiotrack is None
def HasVideo(self):
return not self.videotrack is None
def GetAudioDuration(self):
if not self.audiotrack:
return 0
return self._gettrackduration_ms(self.audiotrack)
def __del__(self):
self.audiomedia = None
self.audiotrack = None
self.videomedia = None
self.videotrack = None
self.movie = None
def _initgworld(self):
old_port, old_dev = Qdoffs.GetGWorld()
try:
movie_w = self.videodescr['width']
movie_h = self.videodescr['height']
movie_rect = (0, 0, movie_w, movie_h)
self.gworld = Qdoffs.NewGWorld(32, movie_rect, None, None, QDOffscreen.keepLocal)
self.pixmap = self.gworld.GetGWorldPixMap()
Qdoffs.LockPixels(self.pixmap)
Qdoffs.SetGWorld(self.gworld.as_GrafPtr(), None)
Qd.EraseRect(movie_rect)
self.movie.SetMovieGWorld(self.gworld.as_GrafPtr(), None)
self.movie.SetMovieBox(movie_rect)
self.movie.SetMovieActive(1)
self.movie.MoviesTask(0)
self.movie.SetMoviePlayHints(QuickTime.hintsHighQuality, QuickTime.hintsHighQuality)
# XXXX framerate
finally:
Qdoffs.SetGWorld(old_port, old_dev)
def _gettrackduration_ms(self, track):
tracktime = track.GetTrackDuration()
return self._movietime_to_ms(tracktime)
def _movietime_to_ms(self, time):
value, d1, d2 = Qt.ConvertTimeScale((time, self.movietimescale, None), 1000)
return value
def _videotime_to_ms(self, time):
value, d1, d2 = Qt.ConvertTimeScale((time, self.videotimescale, None), 1000)
return value
def _audiotime_to_ms(self, time):
value, d1, d2 = Qt.ConvertTimeScale((time, self.audiotimescale, None), 1000)
return value
def _videotime_to_movietime(self, time):
value, d1, d2 = Qt.ConvertTimeScale((time, self.videotimescale, None),
self.movietimescale)
return value
def HasAudio(self):
return not self.audiotrack is None
def HasVideo(self):
return not self.videotrack is None
def GetAudioDuration(self):
if not self.audiotrack:
return 0
return self._gettrackduration_ms(self.audiotrack)
def GetVideoDuration(self):
if not self.videotrack:
return 0
return self._gettrackduration_ms(self.videotrack)
def GetAudioFormat(self):
if not self.audiodescr:
return None, None, None, None, None
bps = self.audiodescr['sampleSize']
nch = self.audiodescr['numChannels']
if nch == 1:
channels = ['mono']
elif nch == 2:
channels = ['left', 'right']
else:
channels = map(lambda x: str(x+1), range(nch))
if bps % 8:
# Funny bits-per sample. We pretend not to understand
blocksize = 0
fpb = 0
else:
# QuickTime is easy (for as far as we support it): samples are always a whole
# number of bytes, so frames are nchannels*samplesize, and there's one frame per block.
blocksize = (bps/8)*nch
fpb = 1
if self.audiodescr['dataFormat'] == 'raw ':
encoding = 'linear-excess'
elif self.audiodescr['dataFormat'] == 'twos':
encoding = 'linear-signed'
else:
encoding = 'quicktime-coding-%s'%self.audiodescr['dataFormat']
## return audio.format.AudioFormatLinear('quicktime_audio', 'QuickTime Audio Format',
## channels, encoding, blocksize=blocksize, fpb=fpb, bps=bps)
return channels, encoding, blocksize, fpb, bps
def GetAudioFrameRate(self):
if not self.audiodescr:
return None
return int(self.audiodescr['sampleRate'])
def GetVideoFormat(self):
width = self.videodescr['width']
height = self.videodescr['height']
return VideoFormat('dummy_format', 'Dummy Video Format', width, height, macrgb)
def GetVideoFrameRate(self):
tv = self.videocurtime
if tv == None:
tv = 0
flags = QuickTime.nextTimeStep|QuickTime.nextTimeEdgeOK
tv, dur = self.videomedia.GetMediaNextInterestingTime(flags, tv, 1.0)
dur = self._videotime_to_ms(dur)
return int((1000.0/dur)+0.5)
def ReadAudio(self, nframes, time=None):
if not time is None:
self.audiocurtime = time
flags = QuickTime.nextTimeStep|QuickTime.nextTimeEdgeOK
if self.audiocurtime == None:
self.audiocurtime = 0
tv = self.audiomedia.GetMediaNextInterestingTimeOnly(flags, self.audiocurtime, 1.0)
if tv < 0 or (self.audiocurtime and tv < self.audiocurtime):
return self._audiotime_to_ms(self.audiocurtime), None
h = Res.Handle('')
desc_h = Res.Handle('')
size, actualtime, sampleduration, desc_index, actualcount, flags = \
self.audiomedia.GetMediaSample(h, 0, tv, desc_h, nframes)
self.audiocurtime = actualtime + actualcount*sampleduration
return self._audiotime_to_ms(actualtime), h.data
def ReadVideo(self, time=None):
if not time is None:
self.videocurtime = time
flags = QuickTime.nextTimeStep
if self.videocurtime == None:
flags = flags | QuickTime.nextTimeEdgeOK
self.videocurtime = 0
tv = self.videomedia.GetMediaNextInterestingTimeOnly(flags, self.videocurtime, 1.0)
if tv < 0 or (self.videocurtime and tv <= self.videocurtime):
return self._videotime_to_ms(self.videocurtime), None
self.videocurtime = tv
moviecurtime = self._videotime_to_movietime(self.videocurtime)
self.movie.SetMovieTimeValue(moviecurtime)
self.movie.MoviesTask(0)
return self._videotime_to_ms(self.videocurtime), self._getpixmapcontent()
def _getpixmapcontent(self):
"""Shuffle the offscreen PixMap data, because it may have funny stride values"""
rowbytes = Qdoffs.GetPixRowBytes(self.pixmap)
width = self.videodescr['width']
height = self.videodescr['height']
start = 0
rv = ''
for i in range(height):
nextline = Qdoffs.GetPixMapBytes(self.pixmap, start, width*4)
start = start + rowbytes
rv = rv + nextline
return rv
def GetVideoDuration(self):
if not self.videotrack:
return 0
return self._gettrackduration_ms(self.videotrack)
def GetAudioFormat(self):
if not self.audiodescr:
return None, None, None, None, None
bps = self.audiodescr['sampleSize']
nch = self.audiodescr['numChannels']
if nch == 1:
channels = ['mono']
elif nch == 2:
channels = ['left', 'right']
else:
channels = map(lambda x: str(x+1), range(nch))
if bps % 8:
# Funny bits-per sample. We pretend not to understand
blocksize = 0
fpb = 0
else:
# QuickTime is easy (for as far as we support it): samples are always a whole
# number of bytes, so frames are nchannels*samplesize, and there's one frame per block.
blocksize = (bps/8)*nch
fpb = 1
if self.audiodescr['dataFormat'] == 'raw ':
encoding = 'linear-excess'
elif self.audiodescr['dataFormat'] == 'twos':
encoding = 'linear-signed'
else:
encoding = 'quicktime-coding-%s'%self.audiodescr['dataFormat']
## return audio.format.AudioFormatLinear('quicktime_audio', 'QuickTime Audio Format',
## channels, encoding, blocksize=blocksize, fpb=fpb, bps=bps)
return channels, encoding, blocksize, fpb, bps
def GetAudioFrameRate(self):
if not self.audiodescr:
return None
return int(self.audiodescr['sampleRate'])
def GetVideoFormat(self):
width = self.videodescr['width']
height = self.videodescr['height']
return VideoFormat('dummy_format', 'Dummy Video Format', width, height, macrgb)
def GetVideoFrameRate(self):
tv = self.videocurtime
if tv == None:
tv = 0
flags = QuickTime.nextTimeStep|QuickTime.nextTimeEdgeOK
tv, dur = self.videomedia.GetMediaNextInterestingTime(flags, tv, 1.0)
dur = self._videotime_to_ms(dur)
return int((1000.0/dur)+0.5)
def ReadAudio(self, nframes, time=None):
if not time is None:
self.audiocurtime = time
flags = QuickTime.nextTimeStep|QuickTime.nextTimeEdgeOK
if self.audiocurtime == None:
self.audiocurtime = 0
tv = self.audiomedia.GetMediaNextInterestingTimeOnly(flags, self.audiocurtime, 1.0)
if tv < 0 or (self.audiocurtime and tv < self.audiocurtime):
return self._audiotime_to_ms(self.audiocurtime), None
h = Res.Handle('')
desc_h = Res.Handle('')
size, actualtime, sampleduration, desc_index, actualcount, flags = \
self.audiomedia.GetMediaSample(h, 0, tv, desc_h, nframes)
self.audiocurtime = actualtime + actualcount*sampleduration
return self._audiotime_to_ms(actualtime), h.data
def ReadVideo(self, time=None):
if not time is None:
self.videocurtime = time
flags = QuickTime.nextTimeStep
if self.videocurtime == None:
flags = flags | QuickTime.nextTimeEdgeOK
self.videocurtime = 0
tv = self.videomedia.GetMediaNextInterestingTimeOnly(flags, self.videocurtime, 1.0)
if tv < 0 or (self.videocurtime and tv <= self.videocurtime):
return self._videotime_to_ms(self.videocurtime), None
self.videocurtime = tv
moviecurtime = self._videotime_to_movietime(self.videocurtime)
self.movie.SetMovieTimeValue(moviecurtime)
self.movie.MoviesTask(0)
return self._videotime_to_ms(self.videocurtime), self._getpixmapcontent()
def _getpixmapcontent(self):
"""Shuffle the offscreen PixMap data, because it may have funny stride values"""
rowbytes = Qdoffs.GetPixRowBytes(self.pixmap)
width = self.videodescr['width']
height = self.videodescr['height']
start = 0
rv = ''
for i in range(height):
nextline = Qdoffs.GetPixMapBytes(self.pixmap, start, width*4)
start = start + rowbytes
rv = rv + nextline
return rv
def reader(url):
try:
rdr = _Reader(url)
except IOError:
return None
return rdr
try:
rdr = _Reader(url)
except IOError:
return None
return rdr
def _test():
import EasyDialogs
try:
import img
except ImportError:
img = None
import MacOS
Qt.EnterMovies()
path = EasyDialogs.AskFileForOpen(message='Video to convert')
if not path: sys.exit(0)
rdr = reader(path)
if not rdr:
sys.exit(1)
dstdir = EasyDialogs.AskFileForSave(message='Name for output folder')
if not dstdir: sys.exit(0)
num = 0
os.mkdir(dstdir)
videofmt = rdr.GetVideoFormat()
imgfmt = videofmt.getformat()
imgw, imgh = videofmt.getsize()
timestamp, data = rdr.ReadVideo()
while data:
fname = 'frame%04.4d.jpg'%num
num = num+1
pname = os.path.join(dstdir, fname)
if not img: print 'Not',
print 'Writing %s, size %dx%d, %d bytes'%(fname, imgw, imgh, len(data))
if img:
wrt = img.writer(imgfmt, pname)
wrt.width = imgw
wrt.height = imgh
wrt.write(data)
timestamp, data = rdr.ReadVideo()
MacOS.SetCreatorAndType(pname, 'ogle', 'JPEG')
if num > 20:
print 'stopping at 20 frames so your disk does not fill up:-)'
break
print 'Total frames:', num
import EasyDialogs
try:
import img
except ImportError:
img = None
import MacOS
Qt.EnterMovies()
path = EasyDialogs.AskFileForOpen(message='Video to convert')
if not path: sys.exit(0)
rdr = reader(path)
if not rdr:
sys.exit(1)
dstdir = EasyDialogs.AskFileForSave(message='Name for output folder')
if not dstdir: sys.exit(0)
num = 0
os.mkdir(dstdir)
videofmt = rdr.GetVideoFormat()
imgfmt = videofmt.getformat()
imgw, imgh = videofmt.getsize()
timestamp, data = rdr.ReadVideo()
while data:
fname = 'frame%04.4d.jpg'%num
num = num+1
pname = os.path.join(dstdir, fname)
if not img: print 'Not',
print 'Writing %s, size %dx%d, %d bytes'%(fname, imgw, imgh, len(data))
if img:
wrt = img.writer(imgfmt, pname)
wrt.width = imgw
wrt.height = imgh
wrt.write(data)
timestamp, data = rdr.ReadVideo()
MacOS.SetCreatorAndType(pname, 'ogle', 'JPEG')
if num > 20:
print 'stopping at 20 frames so your disk does not fill up:-)'
break
print 'Total frames:', num
if __name__ == '__main__':
_test()
sys.exit(1)
_test()
sys.exit(1)