mirror of https://github.com/python/cpython
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:
parent
0db1ef96ac
commit
7571f30efe
|
@ -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()
|
||||
|
|
@ -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()
|
|
@ -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...
|
|
@ -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()
|
||||
|
Loading…
Reference in New Issue