1 """Tools for use in AppleEvent clients and servers.
3 pack(x) converts a Python object to an AEDesc object
4 unpack(desc) does the reverse
6 packevent(event, parameters, attributes) sets params and attrs in an AEAppleEvent record
7 unpackevent(event) returns the parameters and attributes from an AEAppleEvent record
9 Plus... Lots of classes and routines that help representing AE objects,
10 ranges, conditionals, logicals, etc., so you can write, e.g.:
12 x = Character(1, Document("foobar"))
14 and pack(x) will create an AE object reference equivalent to AppleScript's
16 character 1 of document "foobar"
18 Some of the stuff that appears to be exported from this module comes from other
19 files: the pack stuff from aepack, the objects from aetypes.
26 from Carbon
import AppleEvents
31 from aepack
import pack
, unpack
, coerce, AEDescType
33 Error
= 'aetools.Error'
35 # Special code to unpack an AppleEvent (which is *not* a disguised record!)
36 # Note by Jack: No??!? If I read the docs correctly it *is*....
46 'inte', # this attribute is read only - will be set in AESend
47 'esrc', # this attribute is read only
48 'miss', # this attribute is read only
54 desc
= ae
.AEGetAttributeDesc('miss', 'keyw')
62 dirobj
= ae
.AEGetParamDesc('----', '****')
66 parameters
['----'] = unpack(dirobj
)
71 parameters
[key
] = unpack(ae
.AEGetParamDesc(key
, '****'))
73 for key
in aekeywords
:
75 desc
= ae
.AEGetAttributeDesc(key
, '****')
76 except (AE
.Error
, MacOS
.Error
), msg
:
77 if msg
[0] != -1701 and msg
[0] != -1704:
78 raise sys
.exc_type
, sys
.exc_value
80 attributes
[key
] = unpack(desc
)
81 return parameters
, attributes
83 def packevent(ae
, parameters
= {}, attributes
= {}):
84 for key
, value
in parameters
.items():
85 ae
.AEPutParamDesc(key
, pack(value
))
86 for key
, value
in attributes
.items():
87 ae
.AEPutAttributeDesc(key
, pack(value
))
90 # Support routine for automatically generated Suite interfaces
91 # These routines are also useable for the reverse function.
93 def keysubst(arguments
, keydict
):
94 """Replace long name keys by their 4-char counterparts, and check"""
96 for k
in arguments
.keys():
97 if keydict
.has_key(k
):
100 arguments
[keydict
[k
]] = v
101 elif k
!= '----' and k
not in ok
:
102 raise TypeError, 'Unknown keyword argument: %s'%k
104 def enumsubst(arguments
, key
, edict
):
105 """Substitute a single enum keyword argument, if it occurs"""
106 if not arguments
.has_key(key
) or edict
is None:
111 arguments
[key
] = edict
[v
]
113 raise TypeError, 'Unknown enumerator: %s'%v
115 def decodeerror(arguments
):
116 """Create the 'best' argument for a raise MacOS.Error"""
117 errn
= arguments
['errn']
119 if arguments
.has_key('errs'):
120 err_a2
= arguments
['errs']
122 err_a2
= MacOS
.GetErrorString(errn
)
123 if arguments
.has_key('erob'):
124 err_a3
= arguments
['erob']
128 return (err_a1
, err_a2
, err_a3
)
131 """An AE connection to an application"""
132 _signature
= None # Can be overridden by subclasses
134 def __init__(self
, signature
=None, start
=0, timeout
=0):
135 """Create a communication channel with a particular application.
137 Addressing the application is done by specifying either a
138 4-byte signature, an AEDesc or an object that will __aepack__
141 self
.target_signature
= None
142 if signature
is None:
143 signature
= self
._signature
144 if type(signature
) == AEDescType
:
145 self
.target
= signature
146 elif type(signature
) == InstanceType
and hasattr(signature
, '__aepack__'):
147 self
.target
= signature
.__aepack
__()
148 elif type(signature
) == StringType
and len(signature
) == 4:
149 self
.target
= AE
.AECreateDesc(AppleEvents
.typeApplSignature
, signature
)
150 self
.target_signature
= signature
152 raise TypeError, "signature should be 4-char string or AEDesc"
153 self
.send_flags
= AppleEvents
.kAEWaitReply
154 self
.send_priority
= AppleEvents
.kAENormalPriority
156 self
.send_timeout
= timeout
158 self
.send_timeout
= AppleEvents
.kAEDefaultTimeout
163 """Start the application, if it is not running yet"""
165 self
.send('ascr', 'noop')
167 _launch(self
.target_signature
)
170 """Deprecated, used _start()"""
173 def newevent(self
, code
, subcode
, parameters
= {}, attributes
= {}):
174 """Create a complete structure for an apple event"""
176 event
= AE
.AECreateAppleEvent(code
, subcode
, self
.target
,
177 AppleEvents
.kAutoGenerateReturnID
, AppleEvents
.kAnyTransactionID
)
178 packevent(event
, parameters
, attributes
)
181 def sendevent(self
, event
):
182 """Send a pre-created appleevent, await the reply and unpack it"""
184 reply
= event
.AESend(self
.send_flags
, self
.send_priority
,
186 parameters
, attributes
= unpackevent(reply
)
187 return reply
, parameters
, attributes
189 def send(self
, code
, subcode
, parameters
= {}, attributes
= {}):
190 """Send an appleevent given code/subcode/pars/attrs and unpack the reply"""
191 return self
.sendevent(self
.newevent(code
, subcode
, parameters
, attributes
))
194 # The following events are somehow "standard" and don't seem to appear in any
198 """Send 'activate' command"""
199 self
.send('misc', 'actv')
201 def _get(self
, _object
, as=None, _attributes
={}):
202 """_get: get data from an object
203 Required argument: the object
204 Keyword argument _attributes: AppleEvent attribute dictionary
210 _arguments
= {'----':_object
}
212 _arguments
['rtyp'] = mktype(as)
214 _reply
, _arguments
, _attributes
= self
.send(_code
, _subcode
,
215 _arguments
, _attributes
)
216 if _arguments
.has_key('errn'):
217 raise Error
, decodeerror(_arguments
)
219 if _arguments
.has_key('----'):
220 return _arguments
['----']
222 # Tiny Finder class, for local use only
224 class _miniFinder(TalkTo
):
225 def open(self
, _object
, _attributes
={}, **_arguments
):
226 """open: Open the specified object(s)
227 Required argument: list of objects to open
228 Keyword argument _attributes: AppleEvent attribute dictionary
233 if _arguments
: raise TypeError, 'No optional args expected'
234 _arguments
['----'] = _object
237 _reply
, _arguments
, _attributes
= self
.send(_code
, _subcode
,
238 _arguments
, _attributes
)
239 if _arguments
.has_key('errn'):
240 raise Error
, decodeerror(_arguments
)
241 # XXXX Optionally decode result
242 if _arguments
.has_key('----'):
243 return _arguments
['----']
246 _finder
= _miniFinder('MACS')
248 def _launch(appfile
):
249 """Open a file thru the finder. Specify file by name or fsspec"""
250 _finder
.open(_application_file(('ID ', appfile
)))
253 class _application_file(ComponentItem
):
254 """application file - An application's file on disk"""
257 _application_file
._propdict
= {
259 _application_file
._elemdict
= {
263 # XXXX Should test more, really...
266 target
= AE
.AECreateDesc('sign', 'quil')
267 ae
= AE
.AECreateAppleEvent('aevt', 'oapp', target
, -1, 0)
268 print unpackevent(ae
)
270 ae
= AE
.AECreateAppleEvent('core', 'getd', target
, -1, 0)
271 obj
= Character(2, Word(1, Document(1)))
274 packevent(ae
, {'----': obj
})
275 params
, attrs
= unpackevent(ae
)
279 if __name__
== '__main__':