/Mac/scripts/BuildApplet.py

http://unladen-swallow.googlecode.com/ · Python · 159 lines · 135 code · 12 blank · 12 comment · 33 complexity · de257fddb8e9dafe87f0ee5432007b30 MD5 · raw file

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