mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 11:49:12 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			149 lines
		
	
	
	
		
			5.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			149 lines
		
	
	
	
		
			5.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""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 os
 | 
						|
import MacOS
 | 
						|
import EasyDialogs
 | 
						|
import buildtools
 | 
						|
import getopt
 | 
						|
 | 
						|
if not sys.executable.startswith(sys.exec_prefix):
 | 
						|
    # Oh, the joys of using a python script to bootstrap applicatin bundles
 | 
						|
    # sys.executable points inside the current application bundle. Because this
 | 
						|
    # path contains blanks (two of them actually) this path isn't usable on
 | 
						|
    # #! lines. Reset sys.executable to point to the embedded python interpreter
 | 
						|
    sys.executable = os.path.join(sys.prefix,
 | 
						|
            'Resources/Python.app/Contents/MacOS/Python')
 | 
						|
 | 
						|
    # Just in case we're not in a framework:
 | 
						|
    if not os.path.exists(sys.executable):
 | 
						|
        sys.executable = os.path.join(sys.exec_prefix,  'bin/python')
 | 
						|
 | 
						|
def main():
 | 
						|
    try:
 | 
						|
        buildapplet()
 | 
						|
    except buildtools.BuildError as detail:
 | 
						|
        EasyDialogs.Message(detail)
 | 
						|
 | 
						|
 | 
						|
def buildapplet():
 | 
						|
    buildtools.DEBUG=1
 | 
						|
 | 
						|
    # Find the template
 | 
						|
    # (there's no point in proceeding if we can't find it)
 | 
						|
 | 
						|
    template = buildtools.findtemplate()
 | 
						|
 | 
						|
    # Ask for source text if not specified in sys.argv[1:]
 | 
						|
 | 
						|
    if not sys.argv[1:]:
 | 
						|
        filename = EasyDialogs.AskFileForOpen(message='Select Python source or applet:',
 | 
						|
                typeList=('TEXT', 'APPL'))
 | 
						|
        if not filename:
 | 
						|
            return
 | 
						|
        tp, tf = os.path.split(filename)
 | 
						|
        if tf[-3:] == '.py':
 | 
						|
            tf = tf[:-3]
 | 
						|
        else:
 | 
						|
            tf = tf + '.applet'
 | 
						|
        dstfilename = EasyDialogs.AskFileForSave(message='Save application as:',
 | 
						|
                savedFileName=tf)
 | 
						|
        if not dstfilename: return
 | 
						|
        cr, tp = MacOS.GetCreatorAndType(filename)
 | 
						|
        if tp == 'APPL':
 | 
						|
            buildtools.update(template, filename, dstfilename)
 | 
						|
        else:
 | 
						|
            buildtools.process(template, filename, dstfilename, 1)
 | 
						|
    else:
 | 
						|
 | 
						|
        SHORTOPTS = "o:r:ne:v?PR"
 | 
						|
        LONGOPTS=("output=", "resource=", "noargv", "extra=", "verbose", "help", "python=", "destroot=")
 | 
						|
        try:
 | 
						|
            options, args = getopt.getopt(sys.argv[1:], SHORTOPTS, LONGOPTS)
 | 
						|
        except getopt.error:
 | 
						|
            usage()
 | 
						|
        if options and len(args) > 1:
 | 
						|
            sys.stderr.write("Cannot use options when specifying multiple input files")
 | 
						|
            sys.exit(1)
 | 
						|
        dstfilename = None
 | 
						|
        rsrcfilename = None
 | 
						|
        raw = 0
 | 
						|
        extras = []
 | 
						|
        verbose = None
 | 
						|
        destroot = ''
 | 
						|
        for opt, arg in options:
 | 
						|
            if opt in ('-o', '--output'):
 | 
						|
                dstfilename = arg
 | 
						|
            elif opt in ('-r', '--resource'):
 | 
						|
                rsrcfilename = arg
 | 
						|
            elif opt in ('-n', '--noargv'):
 | 
						|
                raw = 1
 | 
						|
            elif opt in ('-e', '--extra'):
 | 
						|
                if ':' in arg:
 | 
						|
                    arg = arg.split(':')
 | 
						|
                extras.append(arg)
 | 
						|
            elif opt in ('-P', '--python'):
 | 
						|
                # This is a very dirty trick. We set sys.executable
 | 
						|
                # so that bundlebuilder will use this in the #! line
 | 
						|
                # for the applet bootstrap.
 | 
						|
                sys.executable = arg
 | 
						|
            elif opt in ('-v', '--verbose'):
 | 
						|
                verbose = Verbose()
 | 
						|
            elif opt in ('-?', '--help'):
 | 
						|
                usage()
 | 
						|
            elif opt in ('-d', '--destroot'):
 | 
						|
                destroot = arg
 | 
						|
        # On OS9 always be verbose
 | 
						|
        if sys.platform == 'mac' and not verbose:
 | 
						|
            verbose = 'default'
 | 
						|
        # Loop over all files to be processed
 | 
						|
        for filename in args:
 | 
						|
            cr, tp = MacOS.GetCreatorAndType(filename)
 | 
						|
            if tp == 'APPL':
 | 
						|
                buildtools.update(template, filename, dstfilename)
 | 
						|
            else:
 | 
						|
                buildtools.process(template, filename, dstfilename, 1,
 | 
						|
                        rsrcname=rsrcfilename, others=extras, raw=raw,
 | 
						|
                        progress=verbose, destroot=destroot)
 | 
						|
 | 
						|
def usage():
 | 
						|
    print("BuildApplet creates an application from a Python source file")
 | 
						|
    print("Usage:")
 | 
						|
    print("  BuildApplet     interactive, single file, no options")
 | 
						|
    print("  BuildApplet src1.py src2.py ...   non-interactive multiple file")
 | 
						|
    print("  BuildApplet [options] src.py    non-interactive single file")
 | 
						|
    print("Options:")
 | 
						|
    print("  --output o        Output file; default based on source filename, short -o")
 | 
						|
    print("  --resource r      Resource file; default based on source filename, short -r")
 | 
						|
    print("  --noargv          Build applet without drag-and-drop sys.argv emulation, short -n, OSX only")
 | 
						|
    print("  --extra src[:dst] Extra file to put in .app bundle, short -e, OSX only")
 | 
						|
    print("  --verbose         Verbose, short -v")
 | 
						|
    print("  --help            This message, short -?")
 | 
						|
    sys.exit(1)
 | 
						|
 | 
						|
class Verbose:
 | 
						|
    """This class mimics EasyDialogs.ProgressBar but prints to stderr"""
 | 
						|
    def __init__(self, *args):
 | 
						|
        if args and args[0]:
 | 
						|
            self.label(args[0])
 | 
						|
 | 
						|
    def set(self, *args):
 | 
						|
        pass
 | 
						|
 | 
						|
    def inc(self, *args):
 | 
						|
        pass
 | 
						|
 | 
						|
    def label(self, str):
 | 
						|
        sys.stderr.write(str+'\n')
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    main()
 |