10a8c90248264a8b26970b4473770bcc3df8515fJosh Gao"""Tools for use in AppleEvent clients and servers.
20a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
30a8c90248264a8b26970b4473770bcc3df8515fJosh Gaopack(x) converts a Python object to an AEDesc object
40a8c90248264a8b26970b4473770bcc3df8515fJosh Gaounpack(desc) does the reverse
50a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
60a8c90248264a8b26970b4473770bcc3df8515fJosh Gaopackevent(event, parameters, attributes) sets params and attrs in an AEAppleEvent record
70a8c90248264a8b26970b4473770bcc3df8515fJosh Gaounpackevent(event) returns the parameters and attributes from an AEAppleEvent record
80a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
90a8c90248264a8b26970b4473770bcc3df8515fJosh GaoPlus...  Lots of classes and routines that help representing AE objects,
100a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoranges, conditionals, logicals, etc., so you can write, e.g.:
110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    x = Character(1, Document("foobar"))
130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
140a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoand pack(x) will create an AE object reference equivalent to AppleScript's
150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    character 1 of document "foobar"
170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
180a8c90248264a8b26970b4473770bcc3df8515fJosh GaoSome of the stuff that appears to be exported from this module comes from other
190a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofiles: the pack stuff from aepack, the objects from aetypes.
200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao"""
220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
240a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom warnings import warnpy3k
250a8c90248264a8b26970b4473770bcc3df8515fJosh Gaowarnpy3k("In 3.x, the aetools module is removed.", stacklevel=2)
260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
270a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom types import *
280a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom Carbon import AE
290a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom Carbon import Evt
300a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom Carbon import AppleEvents
310a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport MacOS
320a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport sys
330a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport time
340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
350a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom aetypes import *
360a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom aepack import packkey, pack, unpack, coerce, AEDescType
370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
380a8c90248264a8b26970b4473770bcc3df8515fJosh GaoError = 'aetools.Error'
390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Amount of time to wait for program to be launched
410a8c90248264a8b26970b4473770bcc3df8515fJosh GaoLAUNCH_MAX_WAIT_TIME=10
420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Special code to unpack an AppleEvent (which is *not* a disguised record!)
440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Note by Jack: No??!? If I read the docs correctly it *is*....
450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
460a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoaekeywords = [
470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    'tran',
480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    'rtid',
490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    'evcl',
500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    'evid',
510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    'addr',
520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    'optk',
530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    'timo',
540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    'inte', # this attribute is read only - will be set in AESend
550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    'esrc', # this attribute is read only
560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    'miss', # this attribute is read only
570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    'from'  # new in 1.0.1
580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao]
590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
600a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef missed(ae):
610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    try:
620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        desc = ae.AEGetAttributeDesc('miss', 'keyw')
630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    except AE.Error, msg:
640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return None
650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    return desc.data
660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
670a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef unpackevent(ae, formodulename=""):
680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    parameters = {}
690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    try:
700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        dirobj = ae.AEGetParamDesc('----', '****')
710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    except AE.Error:
720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        pass
730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    else:
740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        parameters['----'] = unpack(dirobj, formodulename)
750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        del dirobj
760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    # Workaround for what I feel is a bug in OSX 10.2: 'errn' won't show up in missed...
770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    try:
780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        dirobj = ae.AEGetParamDesc('errn', '****')
790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    except AE.Error:
800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        pass
810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    else:
820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        parameters['errn'] = unpack(dirobj, formodulename)
830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        del dirobj
840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    while 1:
850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        key = missed(ae)
860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if not key: break
870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        parameters[key] = unpack(ae.AEGetParamDesc(key, '****'), formodulename)
880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    attributes = {}
890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    for key in aekeywords:
900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        try:
910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            desc = ae.AEGetAttributeDesc(key, '****')
920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        except (AE.Error, MacOS.Error), msg:
930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if msg[0] != -1701 and msg[0] != -1704:
940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                raise
950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            continue
960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        attributes[key] = unpack(desc, formodulename)
970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    return parameters, attributes
980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
990a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef packevent(ae, parameters = {}, attributes = {}):
1000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    for key, value in parameters.items():
1010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        packkey(ae, key, value)
1020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    for key, value in attributes.items():
1030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        ae.AEPutAttributeDesc(key, pack(value))
1040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
1060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Support routine for automatically generated Suite interfaces
1070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# These routines are also useable for the reverse function.
1080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
1090a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef keysubst(arguments, keydict):
1100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Replace long name keys by their 4-char counterparts, and check"""
1110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ok = keydict.values()
1120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    for k in arguments.keys():
1130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if k in keydict:
1140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            v = arguments[k]
1150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            del arguments[k]
1160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            arguments[keydict[k]] = v
1170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        elif k != '----' and k not in ok:
1180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise TypeError, 'Unknown keyword argument: %s'%k
1190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1200a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef enumsubst(arguments, key, edict):
1210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Substitute a single enum keyword argument, if it occurs"""
1220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if key not in arguments or edict is None:
1230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return
1240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    v = arguments[key]
1250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ok = edict.values()
1260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if v in edict:
1270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        arguments[key] = Enum(edict[v])
1280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    elif not v in ok:
1290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        raise TypeError, 'Unknown enumerator: %s'%v
1300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1310a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef decodeerror(arguments):
1320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Create the 'best' argument for a raise MacOS.Error"""
1330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    errn = arguments['errn']
1340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    err_a1 = errn
1350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if 'errs' in arguments:
1360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        err_a2 = arguments['errs']
1370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    else:
1380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        err_a2 = MacOS.GetErrorString(errn)
1390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if 'erob' in arguments:
1400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        err_a3 = arguments['erob']
1410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    else:
1420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        err_a3 = None
1430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    return (err_a1, err_a2, err_a3)
1450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1460a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass TalkTo:
1470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """An AE connection to an application"""
1480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    _signature = None   # Can be overridden by subclasses
1490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    _moduleName = None  # Can be overridden by subclasses
1500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    _elemdict = {}      # Can be overridden by subclasses
1510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    _propdict = {}      # Can be overridden by subclasses
1520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    __eventloop_initialized = 0
1540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __ensure_WMAvailable(klass):
1550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if klass.__eventloop_initialized: return 1
1560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if not MacOS.WMAvailable(): return 0
1570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # Workaround for a but in MacOSX 10.2: we must have an event
1580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # loop before we can call AESend.
1590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Evt.WaitNextEvent(0,0)
1600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return 1
1610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    __ensure_WMAvailable = classmethod(__ensure_WMAvailable)
1620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __init__(self, signature=None, start=0, timeout=0):
1640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Create a communication channel with a particular application.
1650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Addressing the application is done by specifying either a
1670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        4-byte signature, an AEDesc or an object that will __aepack__
1680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        to an AEDesc.
1690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """
1700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.target_signature = None
1710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if signature is None:
1720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            signature = self._signature
1730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if type(signature) == AEDescType:
1740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.target = signature
1750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        elif type(signature) == InstanceType and hasattr(signature, '__aepack__'):
1760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.target = signature.__aepack__()
1770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        elif type(signature) == StringType and len(signature) == 4:
1780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.target = AE.AECreateDesc(AppleEvents.typeApplSignature, signature)
1790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.target_signature = signature
1800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
1810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise TypeError, "signature should be 4-char string or AEDesc"
1820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.send_flags = AppleEvents.kAEWaitReply
1830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.send_priority = AppleEvents.kAENormalPriority
1840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if timeout:
1850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.send_timeout = timeout
1860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
1870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.send_timeout = AppleEvents.kAEDefaultTimeout
1880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if start:
1890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self._start()
1900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def _start(self):
1920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Start the application, if it is not running yet"""
1930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        try:
1940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.send('ascr', 'noop')
1950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        except AE.Error:
1960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            _launch(self.target_signature)
1970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            for i in range(LAUNCH_MAX_WAIT_TIME):
1980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                try:
1990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    self.send('ascr', 'noop')
2000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                except AE.Error:
2010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    pass
2020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                else:
2030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    break
2040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                time.sleep(1)
2050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def start(self):
2070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Deprecated, used _start()"""
2080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self._start()
2090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def newevent(self, code, subcode, parameters = {}, attributes = {}):
2110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Create a complete structure for an apple event"""
2120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        event = AE.AECreateAppleEvent(code, subcode, self.target,
2140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                  AppleEvents.kAutoGenerateReturnID, AppleEvents.kAnyTransactionID)
2150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        packevent(event, parameters, attributes)
2160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return event
2170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def sendevent(self, event):
2190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Send a pre-created appleevent, await the reply and unpack it"""
2200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if not self.__ensure_WMAvailable():
2210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise RuntimeError, "No window manager access, cannot send AppleEvent"
2220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        reply = event.AESend(self.send_flags, self.send_priority,
2230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  self.send_timeout)
2240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        parameters, attributes = unpackevent(reply, self._moduleName)
2250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return reply, parameters, attributes
2260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def send(self, code, subcode, parameters = {}, attributes = {}):
2280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Send an appleevent given code/subcode/pars/attrs and unpack the reply"""
2290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return self.sendevent(self.newevent(code, subcode, parameters, attributes))
2300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #
2320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    # The following events are somehow "standard" and don't seem to appear in any
2330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    # suite...
2340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    #
2350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def activate(self):
2360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Send 'activate' command"""
2370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.send('misc', 'actv')
2380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def _get(self, _object, asfile=None, _attributes={}):
2400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """_get: get data from an object
2410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Required argument: the object
2420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Keyword argument _attributes: AppleEvent attribute dictionary
2430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Returns: the data
2440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """
2450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        _code = 'core'
2460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        _subcode = 'getd'
2470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        _arguments = {'----':_object}
2490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if asfile:
2500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            _arguments['rtyp'] = mktype(asfile)
2510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        _reply, _arguments, _attributes = self.send(_code, _subcode,
2530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                _arguments, _attributes)
2540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if 'errn' in _arguments:
2550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise Error, decodeerror(_arguments)
2560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if '----' in _arguments:
2580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return _arguments['----']
2590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if asfile:
2600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                item.__class__ = asfile
2610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return item
2620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    get = _get
2640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    _argmap_set = {
2660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        'to' : 'data',
2670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    }
2680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def _set(self, _object, _attributes={}, **_arguments):
2700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """set: Set an object's data.
2710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Required argument: the object for the command
2720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Keyword argument to: The new value.
2730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Keyword argument _attributes: AppleEvent attribute dictionary
2740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """
2750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        _code = 'core'
2760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        _subcode = 'setd'
2770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        keysubst(_arguments, self._argmap_set)
2790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        _arguments['----'] = _object
2800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        _reply, _arguments, _attributes = self.send(_code, _subcode,
2830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                _arguments, _attributes)
2840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if _arguments.get('errn', 0):
2850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise Error, decodeerror(_arguments)
2860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # XXXX Optionally decode result
2870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if '----' in _arguments:
2880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return _arguments['----']
2890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    set = _set
2910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    # Magic glue to allow suite-generated classes to function somewhat
2930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    # like the "application" class in OSA.
2940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __getattr__(self, name):
2960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if name in self._elemdict:
2970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            cls = self._elemdict[name]
2980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return DelayedComponentItem(cls, None)
2990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if name in self._propdict:
3000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            cls = self._propdict[name]
3010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return cls()
3020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        raise AttributeError, name
3030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Tiny Finder class, for local use only
3050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3060a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass _miniFinder(TalkTo):
3070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def open(self, _object, _attributes={}, **_arguments):
3080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """open: Open the specified object(s)
3090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Required argument: list of objects to open
3100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Keyword argument _attributes: AppleEvent attribute dictionary
3110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """
3120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        _code = 'aevt'
3130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        _subcode = 'odoc'
3140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if _arguments: raise TypeError, 'No optional args expected'
3160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        _arguments['----'] = _object
3170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        _reply, _arguments, _attributes = self.send(_code, _subcode,
3200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                _arguments, _attributes)
3210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if 'errn' in _arguments:
3220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise Error, decodeerror(_arguments)
3230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # XXXX Optionally decode result
3240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if '----' in _arguments:
3250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return _arguments['----']
3260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#pass
3270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao_finder = _miniFinder('MACS')
3290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3300a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef _launch(appfile):
3310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Open a file thru the finder. Specify file by name or fsspec"""
3320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    _finder.open(_application_file(('ID  ', appfile)))
3330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3350a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass _application_file(ComponentItem):
3360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """application file - An application's file on disk"""
3370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    want = 'appf'
3380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao_application_file._propdict = {
3400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao}
3410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao_application_file._elemdict = {
3420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao}
3430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Test program
3450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# XXXX Should test more, really...
3460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3470a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef test():
3480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    target = AE.AECreateDesc('sign', 'quil')
3490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ae = AE.AECreateAppleEvent('aevt', 'oapp', target, -1, 0)
3500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print unpackevent(ae)
3510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    raw_input(":")
3520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ae = AE.AECreateAppleEvent('core', 'getd', target, -1, 0)
3530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    obj = Character(2, Word(1, Document(1)))
3540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print obj
3550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print repr(obj)
3560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    packevent(ae, {'----': obj})
3570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    params, attrs = unpackevent(ae)
3580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print params['----']
3590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    raw_input(":")
3600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3610a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoif __name__ == '__main__':
3620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    test()
3630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    sys.exit(1)
364