File: pymailgui-products/unzipped/build/build-app-exe/macosx/unused-defunct/build-large-147Mzip-200Mlive.py
#!/usr/bin/env python3 """ ============================================================================= Make a Mac OS X App bundle (folder), using py2app. Based on the more-complicated build.py of PyEdit. Main file: run me in this folder to build the app. An app allows text files to be associated to auto-open in PyEdit on clicks; makes the program immune from Python changes; requires no Python installs; and better supports file drag-and-drops, program icons, and more (but also does a woefully-good job of hiding user-config source files and auto-saves!). Mac app also required... a mac-format .icns icon (the latter became an iconify.py extension), and fixfrozenpaths.py's context configurations. Besides the executable, the app needs: -MailConfigs: its files must be source code, and user-visible and editable; -icon for the exe/app (window borders/app bar for Windows/Linux); -UserGuide.html and docetc items it uses at runtime; py2app sets the cwd to the bundle's Contents/Resource folder in all cases: add '.' to sys.path, and use files copied to .=Resources, to which __file__ will refer. Associations are irrelevant and unused here. NOTE: it's assumed that the frozen app, plus the Python and Tk included in the app bundle are univeral binaries, supporting both 64- and 32-bit machines. This appears to be so, though the app's portability to older OS X versions remains to be shown (10.11 El Capitan is build host). ============================================================================= """ import os, sys, shutil join, sep = os.path.join, os.path.sep force = len(sys.argv) > 1 # remake icon if any arg startdir = os.getcwd() # this build script's dir # 'python3' fails in both IDLE and PyEdit RunCode (env's PATH not inherited?) python = '/usr/local/bin/python3' # sys.executable (else proxy in PyEdit?) #---------------------------------------------------------------------------- # make app's icon if one doesn't already exist #---------------------------------------------------------------------------- iconship = join('..', '..', '..', 'icons') iconmake = join('..', '..', 'build-icons') iconname = 'pymailgui' iconfile = iconname + '.icns' # step into icon build dir and make if force or not os.path.exists(iconship + sep + iconfile): os.chdir(iconmake) #os.system('iconutil -c icns %s.iconset' % iconname) # Apple util #os.system('./resize-on-mac.sh Pyedit1024new images-pyedit') # just once os.system('%s iconify.py -mac images-pyedit %s' % (python, iconname)) # iconify 2.0 os.chdir(startdir) shutil.move(join(iconmake, iconfile), join(iconship, iconfile)) # mv to ship #---------------------------------------------------------------------------- # first, copy source tree to temp folder to avoid accidental code loss; # [update - setup and teardown steps are now automated (run this script in # its dir), and Info.plist edits are now automatic by setup.py options;] #---------------------------------------------------------------------------- # automated setup - run in this file's dir temp = '/Users/blue/Desktop/tempsrc' # cp can't include self! if os.path.exists(temp): shutil.rmtree(temp) os.mkdir(temp) # move all to temp (no PP4E+TextEditor moves needed) shutil.copytree('../../../../pymailgui', temp+'/pymailgui', symlinks=True) shutil.copy('setup.py', temp+'/pymailgui') # add setup script to root os.chdir(temp+'/pymailgui') # goto temp build dir #---------------------------------------------------------------------------- # Drop big and irrelevant folders, plus any personal email stuff #---------------------------------------------------------------------------- # 1) strip the 400M+ nested PyEdit build dirs pyeditbuild = 'PyMailGui-PP4E/PP4E/Gui/TextEditor/build' shutil.rmtree(pyeditbuild) os.mkdir(pyeditbuild) dummy = open(join(pyeditbuild, 'README.txt'), 'w') dummy.write('Content removed: see PyEdit for its build scripts.\n') dummy.close() # else in-use on rmtree non Win (Mac?) # 2) pyedit auto-saves; pass on reinstating zipped examples in docetc/examples autosave_pmg = 'PyMailGui-PP4E/__pyedit-autosaves__' autosave_pe = 'PyMailGui-PP4E/PP4E/Gui/TextEditor/__pyedit-autosaves__' for asave in (autosave_pmg, autosave_pe): for item in os.listdir(asave): if item != 'README-autosaves.txt': itempath = join(asave, item) print('Removing', itempath) os.remove(itempath) # 3) TempParts; pass on reinstating zipped example in docetc/examples tempparts = 'PyMailGui-PP4E/TempParts' for item in os.listdir(tempparts): if item not in ['README-TempParts.txt', 'DSC00565.JPG', 'DSC03890.JPG']: itempath = join(tempparts, item) print('Removing', itempath) os.remove(itempath) # 4) sent mail; very dangerous... print('Replacing sentmail') sentmail = 'PyMailGui-PP4E/sentmail.txt' os.remove(sentmail) os.rename('PyMailGui-PP4E/sentmail-save.txt', sentmail) #---------------------------------------------------------------------------- # cp so use name for both the app-bundle folder and auto-menu title; # this name must also be used in this project's setup.py file here; # we can't rename these after the build, and the launcher is ingrained; #---------------------------------------------------------------------------- # shutil.copy('textEditor.py', 'PyEdit.py') # not here: rename after launcher app built ahead #---------------------------------------------------------------------------- # build app-bundle folder in ./dist, using ./setup.py, copying N extras # to the main Resources folder along with the generated program itself; # this uses --resources to copy non-code extras, and -extras-scripts to # also freeze related scripts shipped with mergeall, so that they can # be run from the app's Content/MacOS folder without a ".py" extension # and without requiring a separate Python install. # # Update: --extras-scripts is unused here, as there are no other scripts. # Instead, we use --package to bundle everything needed for the main # PyMailGui program into the app's Python executable used to run the # launcher. This way, the launcher can spawn PyMailGui as source code # (included in Content/Resources manually) using the app's bundled Python. # That is, all PyMailGui.py requirements are "baked in" to the app's Python # used by the frozen launcher executable. Running PyMailGUI as source also # allows its subfolder structure to remain intact, which is important for # the MailConfigs top-level folder scheme. # # Most other source is for its docs only -- it may not run as source. # Exception: the embedded PyEdit code can be run standalone in this app # with a locally-installed Python, because it's included in full source # form (but get the PyEdit app for a better user experience). #---------------------------------------------------------------------------- extras = [ # tbd: use a 'tools' folder? 'MailConfigs', # ship these in Content/Resources='.' 'README.txt', 'icons', 'docetc', 'UserGuide.html', 'PyMailGui-PP4E', 'Launch_PyEdit.pyw' # runs as source if full PyMailGUI pkg included ] alsofreeze = [ # bake-in other scripts' requirements #'PyMailGui-PP4E/PyMailGui.py' # not required: full --package bundled ] exitstat = os.system( '%s setup.py py2app' ' --iconfile icons/pymailgui.icns' ' --resources %s' ' --package PyMailGui-PP4E' % (python, ','.join(extras)) ) if exitstat: print('ERROR: build failed:', exitstat) sys.exit(exitstat) # don't continue here #---------------------------------------------------------------------------- # cleanup: move and zip the app folder for easy xfer and backup (it has # _very_ many files: nearly 3K files+folders for the current PyEdit App); # [update - teardown actions are now automated (but still no data to copy)] # don't copy extras to Contents/Resources folder here: automatic via the # py2app args above; fixfrozenpaths.py arranges to see these as needed; # DON'T -skipcruft in the zip command: py2app makes a Resources/site.pyc! #---------------------------------------------------------------------------- # zip command: use portable ziptools (vs: 'zip -r %s %s' % (thezip, thedir)) thedir = 'PyMailGUI.app' thezip = thedir + '.zip' code = '/MY-STUFF/Code/ziptools/link' zipit = '%s %s/zip-create.py ../%s %s' % (python, code, thezip, thedir) # move dist product folder here os.chdir(startdir) if os.path.exists('dist'): shutil.rmtree('dist') # nuke bogus retained temp? shutil.move(temp+'/pymailgui/dist', '.') shutil.rmtree(temp) # rm temp build tree # zip the nested app folder - unzip to test and use here or elsewhere if os.path.exists(thezip): shutil.move(thezip, 'prev-'+thezip) # save previous version if os.path.exists(thedir): shutil.rmtree(thedir) # nuke unzipped version os.chdir('dist') shutil.move('Launch_PyMailGUI.app', thedir) os.system(zipit) # run zip in dist: has app dir os.chdir('..') shutil.rmtree('dist') # rm dist: _very_ many files print('Done: see ./%s' % thezip) # +unzip app and copy it to /Applications to make it official