A new home for scripts/applets
EditPythonPrefs - Edit the preferences file (sys.path, python home)
PackLibDir - Convert a sys.path directory to a resource file
RunLibScript - import a module and run as __main__
mkapplet - Create a python applet

The resource files belonging to these should also be stored here, somehow..
diff --git a/Mac/scripts/BuildApplet.py b/Mac/scripts/BuildApplet.py
new file mode 100644
index 0000000..cf90901
--- /dev/null
+++ b/Mac/scripts/BuildApplet.py
@@ -0,0 +1,260 @@
+"""Create an applet from a Python script.
+
+This puts up a dialog asking for a Python source file ('TEXT').
+The output is a file with the same name but its ".py" suffix dropped.
+It is created by copying an applet template and then adding a 'PYC '
+resource named __main__ containing the compiled, marshalled script.
+"""
+
+import sys
+sys.stdout = sys.stderr
+
+import string
+import os
+import marshal
+import imp
+import macfs
+import MacOS
+from Res import *
+
+# .pyc file (and 'PYC ' resource magic number)
+MAGIC = imp.get_magic()
+
+# Template file (searched on sys.path)
+TEMPLATE = "PythonApplet"
+
+# Specification of our resource
+RESTYPE = 'PYC '
+RESNAME = '__main__'
+
+# A resource with this name sets the "owner" (creator) of the destination
+OWNERNAME = "owner resource"
+
+# OpenResFile mode parameters
+READ = 1
+WRITE = 2
+
+def main():
+	
+	# Find the template
+	# (there's no point in proceeding if we can't find it)
+	
+	for p in sys.path:
+		template = os.path.join(p, TEMPLATE)
+		try:
+			tmpl = open(template, "rb")
+			tmpl.close()
+			break
+		except IOError:
+			continue
+	else:
+		die("Template %s not found" % `template`)
+		return
+		
+	# Convert to full pathname
+	template = macfs.FSSpec(template).as_pathname()
+	
+	# Ask for source text if not specified in sys.argv[1:]
+	
+	if not sys.argv[1:]:
+		srcfss, ok = macfs.StandardGetFile('TEXT')
+		if not ok:
+			return
+		filename = srcfss.as_pathname()
+		tp, tf = os.path.split(filename)
+		if tf[-3:] == '.py':
+			tf = tf[:-3]
+		else:
+			tf = tf + '.applet'
+		dstfss, ok = macfs.StandardPutFile('Save application as:', tf)
+		if not ok: return
+		process(template, filename, dstfss.as_pathname())
+	else:
+		
+		# Loop over all files to be processed
+		for filename in sys.argv[1:]:
+			process(template, filename, '')
+
+undefs = ('Atmp', '????', '    ', '\0\0\0\0', 'BINA')
+
+def process(template, filename, output):
+	
+	print "Processing", `filename`, "..."
+	
+	# Read the source and compile it
+	# (there's no point overwriting the destination if it has a syntax error)
+	
+	fp = open(filename)
+	text = fp.read()
+	fp.close()
+	try:
+		code = compile(text, filename, "exec")
+	except (SyntaxError, EOFError):
+		die("Syntax error in script %s" % `filename`)
+		return
+	
+	# Set the destination file name
+	
+	if string.lower(filename[-3:]) == ".py":
+		destname = filename[:-3]
+		rsrcname = destname + '.rsrc'
+	else:
+		destname = filename + ".applet"
+		rsrcname = filename + '.rsrc'
+	
+	if output:
+		destname = output
+	# Copy the data from the template (creating the file as well)
+	
+	tmpl = open(template, "rb")
+	dest = open(destname, "wb")
+	data = tmpl.read()
+	if data:
+		dest.write(data)
+	dest.close()
+	tmpl.close()
+	
+	# Copy the creator of the template to the destination
+	# unless it already got one.  Set type to APPL
+	
+	tctor, ttype = MacOS.GetCreatorAndType(template)
+	ctor, type = MacOS.GetCreatorAndType(destname)
+	if type in undefs: type = 'APPL'
+	if ctor in undefs: ctor = tctor
+	
+	# Open the output resource fork
+	
+	try:
+		output = FSpOpenResFile(destname, WRITE)
+	except MacOS.Error:
+		print "Creating resource fork..."
+		CreateResFile(destname)
+		output = FSpOpenResFile(destname, WRITE)
+	
+	# Copy the resources from the template
+	
+	input = FSpOpenResFile(template, READ)
+	newctor = copyres(input, output)
+	CloseResFile(input)
+	if newctor: ctor = newctor
+	
+	# Copy the resources from the target specific resource template, if any
+	
+	try:
+		input = FSpOpenResFile(rsrcname, READ)
+	except MacOS.Error:
+		pass
+	else:
+		newctor = copyres(input, output)
+		CloseResFile(input)
+		if newctor: ctor = newctor
+	
+	# Now set the creator and type of the destination
+	
+	MacOS.SetCreatorAndType(destname, ctor, type)
+	
+	# Make sure we're manipulating the output resource file now
+	
+	UseResFile(output)
+	
+	# Delete any existing 'PYC 'resource named __main__
+	
+	try:
+		res = Get1NamedResource(RESTYPE, RESNAME)
+		res.RemoveResource()
+	except Error:
+		pass
+	
+	# Create the raw data for the resource from the code object
+	
+	data = marshal.dumps(code)
+	del code
+	data = (MAGIC + '\0\0\0\0') + data
+	
+	# Create the resource and write it
+	
+	id = 0
+	while id < 128:
+		id = Unique1ID(RESTYPE)
+	res = Resource(data)
+	res.AddResource(RESTYPE, id, RESNAME)
+	res.WriteResource()
+	res.ReleaseResource()
+	
+	# Close the output file
+	
+	CloseResFile(output)
+	
+	# Give positive feedback
+	
+	message("Applet %s created." % `destname`)
+
+
+# Copy resources between two resource file descriptors.
+# Exception: don't copy a __main__ resource.
+# If a resource's name is "owner resource", its type is returned
+# (so the caller can use it to set the destination's creator)
+
+def copyres(input, output):
+	ctor = None
+	UseResFile(input)
+	ntypes = Count1Types()
+	for itype in range(1, 1+ntypes):
+		type = Get1IndType(itype)
+		nresources = Count1Resources(type)
+		for ires in range(1, 1+nresources):
+			res = Get1IndResource(type, ires)
+			id, type, name = res.GetResInfo()
+			lcname = string.lower(name)
+			if (type, lcname) == (RESTYPE, RESNAME):
+				continue # Don't copy __main__ from template
+			if lcname == OWNERNAME: ctor = type
+			size = res.size
+			attrs = res.GetResAttrs()
+			print id, type, name, size, hex(attrs)
+			res.LoadResource()
+			res.DetachResource()
+			UseResFile(output)
+			try:
+				res2 = Get1Resource(type, id)
+			except MacOS.Error:
+				res2 = None
+			if res2:
+				print "Overwriting..."
+				res2.RemoveResource()
+			res.AddResource(type, id, name)
+			res.WriteResource()
+			attrs = attrs | res.GetResAttrs()
+			print "New attrs =", hex(attrs)
+			res.SetResAttrs(attrs)
+			UseResFile(input)
+	return ctor
+
+
+# Show a message and exit
+
+def die(str):
+	message(str)
+	sys.exit(1)
+
+
+# Show a message
+
+def message(str, id = 256):
+	from Dlg import *
+	d = GetNewDialog(id, -1)
+	if not d:
+		print "Error:", `str`
+		print "DLOG id =", id, "not found."
+		return
+	tp, h, rect = d.GetDialogItem(2)
+	SetDialogItemText(h, str)
+	while 1:
+		n = ModalDialog(None)
+		if n == 1: break
+	del d
+
+
+if __name__ == '__main__':
+	main()
+