Added 'list_only' option (and modified 'run()' to respect it).
[python/dscho.git] / Mac / Contrib / PythonScript / PythonScript.py
blobb6077aea1119b02ef4ffec2f7dd5ffbc6beb8478
1 """
2 Python script a module to comunicate with apple events
4 v 0.1a2
5 v.0.2 16 april 1998
8 """
9 import sys
10 import getaete
11 import baetools
12 import baetypes
13 import AE
14 import AppleEvents
15 import macfs
16 from types import *
17 #from aetypes import InstanceType
18 from aepack import AEDescType
20 ordinal = {
21 'every': 'all ',
22 'first' : 'firs',
23 'last' : 'last',
24 'any' : 'any ',
25 'middle' : 'midd'}
28 Error = 'PythonScript.Error'
31 class PsEvents:
32 pass
35 class PsClasses:
38 def __getattr__(self, name):
39 try:
40 return DCItem(name, self)
41 except:
42 pass
44 def __repr__(self):
45 if self.form != 'prop':
46 t = type(self.seld)
47 if t == StringType:
48 self.form = 'name'
49 elif baetypes.IsRange(self.seld):
50 self.form = 'rang'
51 elif baetypes.IsComparison(self.seld) or baetypes.IsLogical(self.seld):
52 self.form = 'test'
53 elif t == TupleType:
54 # Breakout: specify both form and seld in a tuple
55 # (if you want ID or rele or somesuch)
56 self.form, self.seld = self.seld
57 elif t == IntType:
58 self.form = 'indx'
59 else:
60 pass
62 if self.seld in ordinal.keys():
63 self.seld = baetypes.Ordinal(ordinal[self.seld])
64 self.form = 'indx'
66 s = "baetypes.ObjectSpecifier(%s, %s, %s" % (`self.want`, `self.form`, `self.seld`)
67 if `self.fr`:
68 s = s + ", %s)" % `self.fr`
69 else:
70 s = s + ")"
71 return s
73 def __str__(self):
74 return self.want
77 def template(self, seld=None, fr=None):
78 self.seld = seld
79 self.fr = fr
81 def template1(self, which, fr=None):
82 self.want = 'prop'
83 self.form = 'prop'
84 self.fr = fr
86 class DCItem:
87 def __init__(self, comp, fr):
88 self.compclass = comp
89 self.fr = fr
91 def __call__(self, which=None):
92 if which:
93 self.compclass = eval('PsClass.%s' % self.compclass)
94 else:
95 try:
96 self.compclass = eval('PsProperties.%s' % self.compclass)
97 except AttributeError:
98 self.compclass = eval('PsClass.%s' % self.compclass)
99 return self.compclass(which, self.fr)
101 class PsClass:
102 pass
104 class PsProperties:
105 pass
108 class PsEnumerations:
109 pass
112 def PsScript(sig=None, Timeout=0, Ignoring=0):
113 elements = {}
114 if sig:
115 target, sig = Signature(sig)
116 pyscript = getaete.Getaete(sig)
117 else:
118 target, sig = Signature('Pyth')
119 pyscript = getaete.Getaete()
120 setattr(PyScript, 'timeout', Timeout)
121 setattr(PyScript, 'ignoring', Ignoring)
122 setattr(PyScript, 'target', target)
123 for key, value in pyscript[0].items():
124 setattr(PsEvents, key, value)
125 for key, value in pyscript[1].items():
126 CreateClass(key, 'PsClasses', value)
127 for val in value[2]:
128 CreateProperty(val[0], 'PsClasses', `val[1]`)
130 if value[3]:
131 for val in value[3]:
132 if val[0] not in elements.keys():
133 elements[val[0]] = val[1]
134 elif len(val[1]) > len(elements[val[0]]):
135 elements[val[0]] = val[1]
137 for key, value in pyscript[2].items():
138 for val in value:
139 setattr(PsEnumerations, val[0], val[1])
141 def CreateClass(newClassName, superClassName, value):
142 parentDict = PsClass.__dict__
143 exec "class %s(%s): pass" % (newClassName, superClassName) in \
144 globals(), parentDict
145 newClassObj = parentDict[newClassName]
146 newClassObj.__init__ = template
147 exec "setattr(newClassObj, 'want', %s)" % `value[0]`
148 if value[2] and value[2][0][0] == 'every':
149 exec "setattr(newClassObj, 'plur', 1)"
151 def CreateProperty(newClassName, superClassName, value):
152 parentDict = PsProperties.__dict__
153 exec "class %s(%s): pass" % (newClassName, superClassName) in \
154 globals(), parentDict
155 newClassObj = parentDict[newClassName]
156 if newClassName == 'Every':
157 value = "baetypes.mkOrdinal('every')"
158 newClassObj.__init__ = template1
159 exec "setattr(newClassObj, 'seld', %s)" % value
161 def Signature(signature):
162 if type(signature) == AEDescType:
163 target = signature
164 elif type(signature) == InstanceType and hasattr(signature, '__aepack__'):
165 target = signature.__aepack__()
166 elif type(signature) == StringType:
167 if len(signature) == 4:
168 target = AE.AECreateDesc(AppleEvents.typeApplSignature, signature)
169 target_signature = signature
170 else:
171 #This should ready be made persistant, so PythonScript 'remembered' where applications were
172 fss, ok = macfs.PromptGetFile('Find the aplication %s' % signature, 'APPL')
173 if ok:
174 target_signature = fss.GetCreatorType()[0]
175 target = AE.AECreateDesc(AppleEvents.typeApplSignature, target_signature)
176 else:
177 raise TypeError, "signature should be 4-char string or AEDesc"
178 return target, target_signature
183 class PyScript(PsEvents):
184 def __init__(self, name, obj=None, **args):
185 desc, code, subcode, rply, message, keywds = name
186 # print 'code', code
187 # print 'subcode', subcode
188 # print 'rply', rply
189 # print 'message', message
190 # print 'keywds', keywds
191 # print 'name', name
192 # print 'obj', obj
193 # print 'args', args
194 self.code = code
195 self.subcode = subcode
196 self.attributes ={}
197 self.arguments = {}
198 if keywds:
199 self.arguments = self.keyargs(keywds, args)
200 self.arguments['----'] = self.keyfms(message[0], obj)
202 ##XXXX Eudora needs this XXXX##
203 if self.arguments['----'] == None:
204 del self.arguments['----']
205 # print 'arguments', self.arguments
206 if self.ignoring or rply[0] == 'null':
207 self.send_flags = AppleEvents.kAENoReply
208 else:
209 self.send_flags = AppleEvents.kAEWaitReply
210 self.send_priority = AppleEvents.kAENormalPriority
211 if self.timeout:
212 self.send_timeout = self.timeout
213 else:
214 self.send_timeout = AppleEvents.kAEDefaultTimeout
217 def keyargs(self, ats, args):
218 # print 'keyargs', ats, args
219 output = {}
220 for arg in args.keys():
221 for at in ats:
222 if at[0] == arg:
223 output[at[1]] = self.keyfms(at[2][0], args[arg])
224 return output
226 def keyfms(self, key, value):
227 # print 'keyfms', 'key', key, `value`
228 if key == 'obj ' or key == 'insl':
229 return eval(`value`)
230 elif key == 'TEXT':
231 return value
232 elif key == 'null':
233 return
234 elif key == 'bool':
235 return baetypes.mkboolean(value)
236 elif key == 'type':
237 try:
238 val = eval('PsClass.%s()' % value)
239 return baetypes.mktype(str(val))
240 except:
241 return baetypes.mktype(value)
242 else:
243 print "I don't know what to put here -- script.keyargs"
244 print key, `value`
245 sys.exit[1]
247 def newevent(self, code, subcode, parameters = {}, attributes = {}):
248 """Create a complete structure for an apple event"""
249 # print code, subcode, parameters, attributes
250 event = AE.AECreateAppleEvent(code, subcode, self.target,
251 AppleEvents.kAutoGenerateReturnID, AppleEvents.kAnyTransactionID)
252 baetools.packevent(event, parameters, attributes)
253 return event
255 def sendevent(self, event):
256 """Send a pre-created appleevent, await the reply and unpack it"""
258 reply = event.AESend(self.send_flags, self.send_priority,
259 self.send_timeout)
260 parameters, attributes = baetools.unpackevent(reply)
261 return reply, parameters, attributes
263 def send(self, code, subcode, parameters = {}, attributes = {}):
264 """Send an appleevent given code/subcode/pars/attrs and unpack the reply"""
265 # print code, subcode, parameters, attributes
266 return self.sendevent(self.newevent(code, subcode, parameters, attributes))
268 def __str__(self):
269 _reply, _arguments, _attributes = self.send(self.code, self.subcode, self.arguments, self.attributes)
271 if _arguments.has_key('errn'):
272 raise baetools.Error, baetools.decodeerror(_arguments)
273 # XXXX Optionally decode result
274 if _arguments.has_key('----'):
275 return str(_arguments['----'])
276 else:
277 return
281 def test():
282 Simp = 'Hermit:Applications:SimpleText'
283 PsScript('MACS', Timeout=60*60*3)
284 # PsScript('CSOm', Timeout=60*60*3)
285 # PsScript('', Timeout=60*60*3)
286 # PyScript('macsoup')
287 ev = PsEvents
288 ps = PsClass
289 # print PsProperties.__dict__
290 # y = script(ev.Open, File('Hermit:Desktop Folder:Lincolnshire Imp'), using=Application_file(Simp))
291 # print baetypes.NProperty('prop', 'prop', 'pnam', baetypes.ObjectSpecifier('cdis', 'indx', 1, None))
292 # y = PyScript(ev.Get, Disk("Hermit").Folder(7).File(1).Name())
293 # y = PyScript(ev.Get, Disk("Hermit").Size(), As='Integer')
294 # y = PyScript(ev.Get, ps.Desktopobject(1).Startup_disk())
295 # y = PyScript(ev.Get, Mailbox(1).File(), as='TEXT')
296 # print 'y', y, type(y)
298 if __name__ == '__main__':
299 test()
300 # sys.exit(1)