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..
This commit is contained in:
Jack Jansen 1995-07-29 13:48:41 +00:00
parent 0db1ef96ac
commit 7571f30efe
4 changed files with 629 additions and 0 deletions

260
Mac/scripts/BuildApplet.py Normal file
View File

@ -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()

View File

@ -0,0 +1,168 @@
"""Edit the Python Preferences file."""
import addpack
addpack.addpack('Tools')
addpack.addpack('bgen')
addpack.addpack('evt')
from Dlg import *
from Events import *
from Res import *
import string
import struct
import macfs
import MacOS
import os
import sys
import Res # For Res.Error
# resource IDs in our own resources (dialogs, etc)
MESSAGE_ID = 256
DIALOG_ID = 131
TEXT_ITEM = 1
OK_ITEM = 2
CANCEL_ITEM = 3
REVERT_ITEM = 4
DIR_ITEM = 5
# Resource IDs in the preferences file
PATH_STRINGS_ID = 128
DIRECTORY_ID = 128
WRITE = 2
smAllScripts = -3
kOnSystemDisk = 0x8000
def restolist(data):
"""Convert STR# resource data to a list of strings"""
if not data:
return []
num, = struct.unpack('h', data[:2])
data = data[2:]
rv = []
for i in range(num):
strlen = ord(data[0])
if strlen < 0: strlen = strlen + 256
str = data[1:strlen+1]
data = data[strlen+1:]
rv.append(str)
return rv
def listtores(list):
"""Convert a list of strings to STR# resource data"""
rv = struct.pack('h', len(list))
for str in list:
rv = rv + chr(len(str)) + str
return rv
def message(str = "Hello, world!", id = MESSAGE_ID):
"""Show a simple alert with a text message"""
d = GetNewDialog(id, -1)
print 'd=', d
tp, h, rect = d.GetDialogItem(2)
SetDialogItemText(h, str)
while 1:
n = ModalDialog(None)
if n == 1: break
def interact(list, pythondir):
"""Let the user interact with the dialog"""
opythondir = pythondir
try:
# Try to go to the "correct" dir for GetDirectory
os.chdir(pythondir.as_pathname())
except os.error:
pass
d = GetNewDialog(DIALOG_ID, -1)
tp, h, rect = d.GetDialogItem(1)
SetDialogItemText(h, string.joinfields(list, '\r'))
while 1:
n = ModalDialog(None)
if n == OK_ITEM:
break
if n == CANCEL_ITEM:
return None
if n == REVERT_ITEM:
return [], pythondir
if n == DIR_ITEM:
fss, ok = macfs.GetDirectory()
if ok:
pythondir = fss
tmp = string.splitfields(GetDialogItemText(h), '\r')
rv = []
for i in tmp:
if i:
rv.append(i)
return rv, pythondir
def main():
try:
h = OpenResFile('EditPythonPrefs.rsrc')
except Res.Error:
pass # Assume we already have acces to our own resource
# Find the preferences folder and our prefs file, create if needed.
vrefnum, dirid = macfs.FindFolder(kOnSystemDisk, 'pref', 0)
preff_fss = macfs.FSSpec((vrefnum, dirid, 'Python Preferences'))
try:
preff_handle = FSpOpenResFile(preff_fss, WRITE)
except Res.Error:
# Create it
message('No preferences file, creating one...')
FSpCreateResFile(preff_fss, 'PYTH', 'pref', smAllScripts)
preff_handle = FSpOpenResFile(preff_fss, WRITE)
# Load the path and directory resources
try:
sr = GetResource('STR#', PATH_STRINGS_ID)
except (MacOS.Error, Res.Error):
message('Cannot find any sys.path resource! (Old python?)')
sys.exit(0)
d = sr.data
l = restolist(d)
try:
dr = GetResource('alis', DIRECTORY_ID)
fss, fss_changed = macfs.RawAlias(dr.data).Resolve()
except (MacOS.Error, Res.Error):
dr = None
fss = macfs.FSSpec(os.getcwd())
fss_changed = 1
# Let the user play away
result = interact(l, fss)
# See what we have to update, and how
if result == None:
sys.exit(0)
pathlist, nfss = result
if nfss != fss:
fss_changed = 1
if fss_changed or pathlist != l:
if fss_changed:
alias = nfss.NewAlias()
if dr:
dr.data = alias.data
dr.ChangedResource()
else:
dr = Resource(alias.data)
dr.AddResource('alis', DIRECTORY_ID, '')
if pathlist != l:
if pathlist == []:
if sr.HomeResFile() == preff_handle:
sr.RemoveResource()
elif sr.HomeResFile() == preff_handle:
sr.data = listtores(pathlist)
sr.ChangedResource()
else:
sr = Resource(listtores(pathlist))
sr.AddResource('STR#', PATH_STRINGS_ID, '')
CloseResFile(preff_handle)
if __name__ == '__main__':
print # Stupid, to init toolboxes...
main()

93
Mac/scripts/PackLibDir.py Normal file
View File

@ -0,0 +1,93 @@
#
# Turn a pyc file into a resource file containing it in 'PYC ' resource form
import addpack
addpack.addpack('Tools')
addpack.addpack('bgen')
addpack.addpack('res')
from Res import *
import Res
from Resources import *
import os
import macfs
import sys
READ = 1
WRITE = 2
smAllScripts = -3
error = 'mkpycresourcefile.error'
def Pstring(str):
if len(str) > 255:
raise ValueError, 'String too large'
return chr(len(str))+str
def createoutput(dst):
"""Create output file. Return handle and first id to use."""
FSpCreateResFile(dst, 'PYTH', 'rsrc', smAllScripts)
output = FSpOpenResFile(dst, WRITE)
UseResFile(output)
num = 128
return output, num
def writemodule(name, id, data):
"""Write pyc code to a PYC resource with given name and id."""
# XXXX Check that it doesn't exist
res = Resource(data)
res.AddResource('PYC ', id, name)
res.WriteResource()
res.ReleaseResource()
def mkpycresourcefile(src, dst):
"""Copy pyc file/dir src to resource file dst."""
if not os.path.isdir(src) and src[-4:] <> '.pyc':
raise error, 'I can only handle .pyc files or directories'
handle, oid = createoutput(dst)
if os.path.isdir(src):
id = handlesubdir(handle, oid, src)
else:
id = handleonepycfile(handle, oid, src)
print 'Wrote',id-oid,'PYC resources to', dst
CloseResFile(handle)
def handleonepycfile(handle, id, file):
"""Copy one pyc file to the open resource file"""
d, name = os.path.split(file)
name = name[:-4]
print ' module', name
writemodule(name, id, open(file, 'rb').read())
return id+1
def handlesubdir(handle, id, srcdir):
"""Recursively scan a directory for pyc files and copy to resources"""
print 'Directory', srcdir
src = os.listdir(srcdir)
for file in src:
file = os.path.join(srcdir, file)
if os.path.isdir(file):
id = handlesubdir(handle, id, file)
elif file[-4:] == '.pyc':
id = handleonepycfile(handle, id, file)
return id
if __name__ == '__main__':
args = sys.argv[1:]
if not args:
ifss, ok = macfs.StandardGetFile('PYC ')
if ok:
args = [ifss.as_pathname()]
else:
ifss, ok = macfs.GetDirectory()
if not ok:
sys.exit(0)
args = [ifss.as_pathname()]
for ifn in args:
ofss, ok = macfs.StandardPutFile('Output for '+os.path.split(ifn)[1])
if not ok:
sys.exit(0)
mkpycresourcefile(ifn, ofss.as_pathname())
sys.exit(1) # So we can see something...

108
Mac/scripts/RunLibScript.py Normal file
View File

@ -0,0 +1,108 @@
"""Import a module while pretending its name is __main__. This
can be used to run scripts from the PackedLib resource file while pretending
they have been double-clicked."""
import imp
import sys
import os
import string
import Dlg
import macfs
DIALOG_ID = 140
OK = 1
CANCEL = 2
SCRIPTNAME=3
ARGV=4
STDIN_CONS=5
STDIN_FILE=6
STDOUT_CONS=7
STDOUT_FILE=8
WORKING_DIR=9
PAUSE=10
def import_as_main(name):
fp, path, (suffix, mode, type) = imp.find_module(name)
if type == imp.PY_SOURCE:
imp.load_source('__main__', path)
elif type == imp.PY_COMPILED:
imp.load_compiled('__main__', path)
elif type == imp.PY_RESOURCE:
imp.load_resource('__main__', path)
def interact():
d = Dlg.GetNewDialog(DIALOG_ID, -1)
wdir = stdin = stdout = None
pause = 0
tp, in_c_h, rect = d.GetDialogItem(STDIN_CONS)
tp, in_f_h, rect = d.GetDialogItem(STDIN_FILE)
tp, out_c_h, rect = d.GetDialogItem(STDOUT_CONS)
tp, out_f_h, rect = d.GetDialogItem(STDOUT_FILE)
tp, pause_h, rect = d.GetDialogItem(PAUSE)
in_c_h = in_c_h.as_Control()
in_f_h = in_f_h.as_Control()
out_c_h = out_c_h.as_Control()
out_f_h = out_f_h.as_Control()
pause_h = pause_h.as_Control()
while 1:
in_c_h.SetControlValue(not stdin)
in_f_h.SetControlValue(not not stdin)
out_c_h.SetControlValue(not stdout)
out_f_h.SetControlValue(not not stdout)
pause_h.SetControlValue(pause)
n = Dlg.ModalDialog(None)
if n == OK:
break
elif n == CANCEL:
sys.exit(0)
elif n == STDIN_CONS:
stdin = None
elif n == STDIN_FILE:
fss, ok = macfs.StandardGetFile('TEXT')
if ok:
stdin = fss
elif n == STDOUT_FILE:
fss, ok = macfs.StandardPutFile('stdout:')
if ok:
stdout = fss
elif n == WORKING_DIR:
fss, ok = macfs.GetDirectory()
if ok:
wdir = fss
elif n == PAUSE:
pause = (not pause)
tp, h, rect = d.GetDialogItem(SCRIPTNAME)
name = Dlg.GetDialogItemText(h)
tp, h, rect = d.GetDialogItem(ARGV)
argv = Dlg.GetDialogItemText(h)
return name, argv, stdin, stdout, wdir, pause
def main():
curdir = os.getcwd()
import Res
Res.OpenResFile('RunLibScript.rsrc')
name, argv, stdin, stdout, wdir, pause = interact()
if not name:
sys.exit(0)
sys.argv = [name] + string.split(argv)
if stdin:
sys.stdin = open(stdin.as_pathname())
if stdout:
sys.stdout = open(stdout.as_pathname(), 'w')
if wdir:
os.chdir(wdir.as_pathname())
else:
os.chdir(curdir)
import_as_main(name)
if pause:
sys.exit(1)
if __name__ == '__main__':
main()