Initial revision
diff --git a/Mac/Contrib/PythonScript/PythonScript.py b/Mac/Contrib/PythonScript/PythonScript.py
new file mode 100644
index 0000000..b6077ae
--- /dev/null
+++ b/Mac/Contrib/PythonScript/PythonScript.py
@@ -0,0 +1,301 @@
+"""
+Python script a module to comunicate with apple events
+
+v 0.1a2
+v.0.2 16 april 1998 
+
+
+"""
+import sys
+import getaete
+import baetools
+import baetypes
+import AE
+import AppleEvents
+import macfs
+from types import *
+#from aetypes import InstanceType
+from aepack import AEDescType
+
+ordinal = {
+'every': 'all ',
+'first' : 'firs',
+'last' : 'last',
+'any' : 'any ',
+'middle' : 'midd'}
+
+
+Error = 'PythonScript.Error'
+
+
+class PsEvents:
+	pass
+
+
+class PsClasses:
+
+	
+	def __getattr__(self, name):
+		try:
+			return DCItem(name, self)
+		except:
+			pass
+		
+	def __repr__(self):
+		if self.form != 'prop':
+			t = type(self.seld)
+			if t == StringType:
+				self.form = 'name'
+			elif baetypes.IsRange(self.seld):
+				self.form = 'rang'
+			elif baetypes.IsComparison(self.seld) or baetypes.IsLogical(self.seld):
+				self.form = 'test'
+			elif t == TupleType:
+			# Breakout: specify both form and seld in a tuple
+			# (if you want ID or rele or somesuch)
+				self.form, self.seld = self.seld
+			elif t == IntType:
+				self.form = 'indx'
+			else:
+				pass
+
+		if self.seld in ordinal.keys():
+			self.seld = baetypes.Ordinal(ordinal[self.seld])
+			self.form = 'indx'
+
+		s = "baetypes.ObjectSpecifier(%s, %s, %s" % (`self.want`, `self.form`, `self.seld`)
+		if `self.fr`:
+			s = s + ", %s)" % `self.fr`
+		else:
+			s = s + ")"
+		return s
+		
+	def __str__(self):
+		return self.want
+		
+		
+def template(self, seld=None, fr=None):
+	self.seld = seld
+	self.fr = fr
+		
+def template1(self, which, fr=None):
+	self.want = 'prop'
+	self.form = 'prop'
+	self.fr = fr
+	
+class DCItem:
+	def __init__(self, comp, fr):
+		self.compclass = comp
+		self.fr = fr
+		
+	def __call__(self, which=None):
+		if which:
+			self.compclass = eval('PsClass.%s' % self.compclass)
+		else:
+			try:
+				self.compclass = eval('PsProperties.%s' % self.compclass)
+			except AttributeError:
+				self.compclass = eval('PsClass.%s' % self.compclass)
+		return self.compclass(which, self.fr)
+
+class PsClass:
+	pass
+
+class PsProperties:
+	pass				
+
+
+class PsEnumerations:
+	pass
+
+			
+def PsScript(sig=None, Timeout=0, Ignoring=0):
+	elements = {}
+	if sig:
+		target, sig = Signature(sig)
+		pyscript = getaete.Getaete(sig)
+	else:
+		target, sig = Signature('Pyth')
+		pyscript = getaete.Getaete()
+	setattr(PyScript, 'timeout', Timeout)
+	setattr(PyScript, 'ignoring', Ignoring)
+	setattr(PyScript, 'target', target)
+	for key, value in pyscript[0].items():
+		setattr(PsEvents, key, value)
+	for key, value in pyscript[1].items():
+		CreateClass(key, 'PsClasses', value)
+		for val in value[2]:
+			CreateProperty(val[0], 'PsClasses', `val[1]`)
+			
+		if value[3]:
+			for val in value[3]:
+				if val[0] not in elements.keys():
+					elements[val[0]] = val[1]
+				elif len(val[1]) > len(elements[val[0]]):
+					elements[val[0]] = val[1]
+
+	for key, value in pyscript[2].items():
+		for val in value:
+			setattr(PsEnumerations, val[0], val[1])
+
+def CreateClass(newClassName, superClassName, value):
+	parentDict = PsClass.__dict__
+	exec "class %s(%s): pass" % (newClassName, superClassName) in \
+			globals(), parentDict
+	newClassObj = parentDict[newClassName]
+	newClassObj.__init__ = template
+	exec "setattr(newClassObj, 'want', %s)" % `value[0]`
+	if value[2] and value[2][0][0] == 'every':
+		exec "setattr(newClassObj, 'plur', 1)"
+
+def CreateProperty(newClassName, superClassName, value):
+	parentDict = PsProperties.__dict__
+	exec "class %s(%s): pass" % (newClassName, superClassName) in \
+			globals(), parentDict
+	newClassObj = parentDict[newClassName]
+	if newClassName == 'Every':
+		value = "baetypes.mkOrdinal('every')"
+	newClassObj.__init__ = template1
+	exec "setattr(newClassObj, 'seld', %s)" % value
+
+def Signature(signature):
+	if type(signature) == AEDescType:
+		target = signature
+	elif type(signature) == InstanceType and hasattr(signature, '__aepack__'):
+		target = signature.__aepack__()
+	elif type(signature) == StringType:
+		if len(signature) == 4:
+			target = AE.AECreateDesc(AppleEvents.typeApplSignature, signature)
+			target_signature = signature
+		else:
+			#This should ready be made persistant, so PythonScript 'remembered' where applications were
+			fss, ok = macfs.PromptGetFile('Find the aplication %s' % signature, 'APPL')
+			if ok:
+				target_signature = fss.GetCreatorType()[0]
+				target = AE.AECreateDesc(AppleEvents.typeApplSignature, target_signature)
+	else:
+		raise TypeError, "signature should be 4-char string or AEDesc"
+	return target, target_signature
+
+		
+
+		
+class PyScript(PsEvents):
+	def __init__(self, name, obj=None,  **args):
+		desc, code, subcode, rply, message, keywds = name
+#		print 'code', code
+#		print 'subcode', subcode
+#		print 'rply', rply
+#		print 'message', message
+#		print 'keywds', keywds
+#		print 'name', name
+#		print 'obj', obj
+#		print 'args', args
+		self.code = code
+		self.subcode = subcode
+		self.attributes ={}
+		self.arguments = {}
+		if keywds:
+			self.arguments = self.keyargs(keywds, args)
+		self.arguments['----'] = self.keyfms(message[0], obj)
+
+		##XXXX Eudora needs this XXXX##
+		if self.arguments['----'] == None:
+			del self.arguments['----']
+#		print 'arguments', self.arguments
+		if self.ignoring or rply[0] == 'null':
+			self.send_flags = AppleEvents.kAENoReply
+		else:
+			self.send_flags = AppleEvents.kAEWaitReply
+		self.send_priority = AppleEvents.kAENormalPriority	
+		if self.timeout:
+			self.send_timeout = self.timeout
+		else:
+			self.send_timeout = AppleEvents.kAEDefaultTimeout
+
+
+	def keyargs(self, ats, args):
+#		print 'keyargs', ats, args
+		output = {}
+		for arg in args.keys():
+			for at in ats:
+				if at[0] == arg:
+					output[at[1]] = self.keyfms(at[2][0], args[arg])
+		return output
+				
+	def keyfms(self, key, value):
+#		print 'keyfms', 'key', key, `value`
+		if key == 'obj ' or key == 'insl':
+			return eval(`value`)
+		elif key == 'TEXT':
+			return value
+		elif key == 'null':
+			return 
+		elif key == 'bool':
+			return baetypes.mkboolean(value)
+		elif key == 'type':
+			try:
+				val = eval('PsClass.%s()' % value)
+				return baetypes.mktype(str(val))
+			except:
+				return baetypes.mktype(value)
+		else:
+			print "I don't know what to put here -- script.keyargs"
+			print key, `value`
+			sys.exit[1]
+		
+	def newevent(self, code, subcode, parameters = {}, attributes = {}):
+		"""Create a complete structure for an apple event"""
+#		print code, subcode, parameters, attributes
+		event = AE.AECreateAppleEvent(code, subcode, self.target,
+			  	  AppleEvents.kAutoGenerateReturnID, AppleEvents.kAnyTransactionID)
+		baetools.packevent(event, parameters, attributes)
+		return event
+		
+	def sendevent(self, event):
+		"""Send a pre-created appleevent, await the reply and unpack it"""
+		
+		reply = event.AESend(self.send_flags, self.send_priority,
+							  self.send_timeout)
+		parameters, attributes = baetools.unpackevent(reply)
+		return reply, parameters, attributes
+		
+	def send(self, code, subcode, parameters = {}, attributes = {}):
+		"""Send an appleevent given code/subcode/pars/attrs and unpack the reply"""
+#		print code, subcode, parameters, attributes
+		return self.sendevent(self.newevent(code, subcode, parameters, attributes))
+		
+	def __str__(self):
+		_reply, _arguments, _attributes = self.send(self.code, self.subcode, self.arguments, self.attributes)
+
+		if _arguments.has_key('errn'):
+			raise baetools.Error, baetools.decodeerror(_arguments)
+		# XXXX Optionally decode result
+		if _arguments.has_key('----'):
+			return str(_arguments['----'])
+		else:
+			return 
+
+	
+	
+def test():
+	Simp = 'Hermit:Applications:SimpleText'
+	PsScript('MACS', Timeout=60*60*3)
+#	PsScript('CSOm', Timeout=60*60*3)
+#	PsScript('', Timeout=60*60*3)
+#	PyScript('macsoup')
+	ev = PsEvents
+	ps = PsClass
+#	print PsProperties.__dict__
+#	y = script(ev.Open, File('Hermit:Desktop Folder:Lincolnshire Imp'), using=Application_file(Simp))
+#	print baetypes.NProperty('prop', 'prop', 'pnam',  baetypes.ObjectSpecifier('cdis', 'indx', 1, None))
+#	y = PyScript(ev.Get, Disk("Hermit").Folder(7).File(1).Name())
+#	y = PyScript(ev.Get, Disk("Hermit").Size(), As='Integer')
+#	y = PyScript(ev.Get, ps.Desktopobject(1).Startup_disk())
+#	y = PyScript(ev.Get, Mailbox(1).File(), as='TEXT')
+#	print 'y', y, type(y)
+
+if __name__ == '__main__':
+	test()
+#	sys.exit(1)
+