PageRenderTime 55ms CodeModel.GetById 20ms app.highlight 15ms RepoModel.GetById 16ms app.codeStats 0ms

/Mac/scripts/BuildApplet.py

http://unladen-swallow.googlecode.com/
Python | 159 lines | 142 code | 10 blank | 7 comment | 14 complexity | de257fddb8e9dafe87f0ee5432007b30 MD5 | raw file
  1"""Create an applet from a Python script.
  2
  3This puts up a dialog asking for a Python source file ('TEXT').
  4The output is a file with the same name but its ".py" suffix dropped.
  5It is created by copying an applet template and then adding a 'PYC '
  6resource named __main__ containing the compiled, marshalled script.
  7"""
  8
  9
 10import sys
 11sys.stdout = sys.stderr
 12
 13import os
 14import MacOS
 15try:
 16    import EasyDialogs
 17except ImportError:
 18    EasyDialogs = None
 19import buildtools
 20import getopt
 21
 22if not sys.executable.startswith(sys.exec_prefix):
 23    # Oh, the joys of using a python script to bootstrap applicatin bundles
 24    # sys.executable points inside the current application bundle. Because this
 25    # path contains blanks (two of them actually) this path isn't usable on
 26    # #! lines. Reset sys.executable to point to the embedded python interpreter
 27    sys.executable = os.path.join(sys.prefix,
 28            'Resources/Python.app/Contents/MacOS/Python')
 29
 30    # Just in case we're not in a framework:
 31    if not os.path.exists(sys.executable):
 32        sys.executable = os.path.join(sys.exec_prefix,  'bin/python')
 33
 34def main():
 35    try:
 36        buildapplet()
 37    except buildtools.BuildError, detail:
 38        if EasyDialogs is None:
 39            print detail
 40        else:
 41            EasyDialogs.Message(detail)
 42
 43
 44def buildapplet():
 45    buildtools.DEBUG=1
 46
 47    # Find the template
 48    # (there's no point in proceeding if we can't find it)
 49
 50    template = buildtools.findtemplate()
 51
 52    # Ask for source text if not specified in sys.argv[1:]
 53
 54    if not sys.argv[1:]:
 55        if EasyDialogs is None:
 56            usage()
 57            sys.exit(1)
 58
 59        filename = EasyDialogs.AskFileForOpen(message='Select Python source or applet:',
 60                typeList=('TEXT', 'APPL'))
 61        if not filename:
 62            return
 63        tp, tf = os.path.split(filename)
 64        if tf[-3:] == '.py':
 65            tf = tf[:-3]
 66        else:
 67            tf = tf + '.applet'
 68        dstfilename = EasyDialogs.AskFileForSave(message='Save application as:',
 69                savedFileName=tf)
 70        if not dstfilename: return
 71        cr, tp = MacOS.GetCreatorAndType(filename)
 72        if tp == 'APPL':
 73            buildtools.update(template, filename, dstfilename)
 74        else:
 75            buildtools.process(template, filename, dstfilename, 1)
 76    else:
 77
 78        SHORTOPTS = "o:r:ne:v?PR"
 79        LONGOPTS=("output=", "resource=", "noargv", "extra=", "verbose", "help", "python=", "destroot=")
 80        try:
 81            options, args = getopt.getopt(sys.argv[1:], SHORTOPTS, LONGOPTS)
 82        except getopt.error:
 83            usage()
 84        if options and len(args) > 1:
 85            sys.stderr.write("Cannot use options when specifying multiple input files")
 86            sys.exit(1)
 87        dstfilename = None
 88        rsrcfilename = None
 89        raw = 0
 90        extras = []
 91        verbose = None
 92        destroot = ''
 93        for opt, arg in options:
 94            if opt in ('-o', '--output'):
 95                dstfilename = arg
 96            elif opt in ('-r', '--resource'):
 97                rsrcfilename = arg
 98            elif opt in ('-n', '--noargv'):
 99                raw = 1
100            elif opt in ('-e', '--extra'):
101                if ':' in arg:
102                    arg = arg.split(':')
103                extras.append(arg)
104            elif opt in ('-P', '--python'):
105                # This is a very dirty trick. We set sys.executable
106                # so that bundlebuilder will use this in the #! line
107                # for the applet bootstrap.
108                sys.executable = arg
109            elif opt in ('-v', '--verbose'):
110                verbose = Verbose()
111            elif opt in ('-?', '--help'):
112                usage()
113            elif opt in ('-d', '--destroot'):
114                destroot = arg
115        # On OS9 always be verbose
116        if sys.platform == 'mac' and not verbose:
117            verbose = 'default'
118        # Loop over all files to be processed
119        for filename in args:
120            cr, tp = MacOS.GetCreatorAndType(filename)
121            if tp == 'APPL':
122                buildtools.update(template, filename, dstfilename)
123            else:
124                buildtools.process(template, filename, dstfilename, 1,
125                        rsrcname=rsrcfilename, others=extras, raw=raw,
126                        progress=verbose, destroot=destroot)
127
128def usage():
129    print "BuildApplet creates an application from a Python source file"
130    print "Usage:"
131    print "  BuildApplet     interactive, single file, no options"
132    print "  BuildApplet src1.py src2.py ...   non-interactive multiple file"
133    print "  BuildApplet [options] src.py    non-interactive single file"
134    print "Options:"
135    print "  --output o        Output file; default based on source filename, short -o"
136    print "  --resource r      Resource file; default based on source filename, short -r"
137    print "  --noargv          Build applet without drag-and-drop sys.argv emulation, short -n, OSX only"
138    print "  --extra src[:dst] Extra file to put in .app bundle, short -e, OSX only"
139    print "  --verbose         Verbose, short -v"
140    print "  --help            This message, short -?"
141    sys.exit(1)
142
143class Verbose:
144    """This class mimics EasyDialogs.ProgressBar but prints to stderr"""
145    def __init__(self, *args):
146        if args and args[0]:
147            self.label(args[0])
148
149    def set(self, *args):
150        pass
151
152    def inc(self, *args):
153        pass
154
155    def label(self, str):
156        sys.stderr.write(str+'\n')
157
158if __name__ == '__main__':
159    main()