home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / MacHacksBug / Python 1.5.2c1 / Mac / Contrib / PythonScript / PythonScript.py < prev    next >
Encoding:
Python Source  |  2000-06-23  |  7.9 KB  |  302 lines

  1. """
  2. Python script a module to comunicate with apple events
  3.  
  4. v 0.1a2
  5. v.0.2 16 april 1998 
  6.  
  7.  
  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
  19.  
  20. ordinal = {
  21. 'every': 'all ',
  22. 'first' : 'firs',
  23. 'last' : 'last',
  24. 'any' : 'any ',
  25. 'middle' : 'midd'}
  26.  
  27.  
  28. Error = 'PythonScript.Error'
  29.  
  30.  
  31. class PsEvents:
  32.     pass
  33.  
  34.  
  35. class PsClasses:
  36.  
  37.     
  38.     def __getattr__(self, name):
  39.         try:
  40.             return DCItem(name, self)
  41.         except:
  42.             pass
  43.         
  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
  61.  
  62.         if self.seld in ordinal.keys():
  63.             self.seld = baetypes.Ordinal(ordinal[self.seld])
  64.             self.form = 'indx'
  65.  
  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
  72.         
  73.     def __str__(self):
  74.         return self.want
  75.         
  76.         
  77. def template(self, seld=None, fr=None):
  78.     self.seld = seld
  79.     self.fr = fr
  80.         
  81. def template1(self, which, fr=None):
  82.     self.want = 'prop'
  83.     self.form = 'prop'
  84.     self.fr = fr
  85.     
  86. class DCItem:
  87.     def __init__(self, comp, fr):
  88.         self.compclass = comp
  89.         self.fr = fr
  90.         
  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)
  100.  
  101. class PsClass:
  102.     pass
  103.  
  104. class PsProperties:
  105.     pass                
  106.  
  107.  
  108. class PsEnumerations:
  109.     pass
  110.  
  111.             
  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]`)
  129.             
  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]
  136.  
  137.     for key, value in pyscript[2].items():
  138.         for val in value:
  139.             setattr(PsEnumerations, val[0], val[1])
  140.  
  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)"
  150.  
  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
  160.  
  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
  179.  
  180.         
  181.  
  182.         
  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)
  201.  
  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
  215.  
  216.  
  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
  225.                 
  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]
  246.         
  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
  254.         
  255.     def sendevent(self, event):
  256.         """Send a pre-created appleevent, await the reply and unpack it"""
  257.         
  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
  262.         
  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))
  267.         
  268.     def __str__(self):
  269.         _reply, _arguments, _attributes = self.send(self.code, self.subcode, self.arguments, self.attributes)
  270.  
  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 
  278.  
  279.     
  280.     
  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)
  297.  
  298. if __name__ == '__main__':
  299.     test()
  300. #    sys.exit(1)
  301.     
  302.