source: trunk/makeMacApp.py @ 3166

Last change on this file since 3166 was 3166, checked in by toby, 6 years ago

Misc Py3 fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 7.2 KB
Line 
1#!/usr/bin/env python
2'''
3*makeMacApp: Create Mac Applet*
4===============================
5
6This script creates an AppleScript app to launch GSAS-II. The app is
7created in the directory where the GSAS-II script is located.
8A softlink to Python is created, but is named GSAS-II, so that
9GSAS-II shows up as the name of the app rather than Python in the
10menu bar, etc. Note that this requires finding an app version of Python
11(expected name .../Resources/Python.app/Contents/MacOS/Python in
12directory tree of the calling python interpreter).
13
14Run this script with one optional argument, the path to the GSASII.py
15The script path may be specified relative to the current path or given
16an absolute path, but will be accessed via an absolute path.
17If no arguments are supplied, the GSASII.py script is assumed to be in the
18same directory as this file.
19
20'''
21import sys, os, os.path, stat, shutil, subprocess, plistlib
22def Usage():
23    print("\n\tUsage: python "+sys.argv[0]+" [<GSAS-II script>]\n")
24    sys.exit()
25
26def RunPython(image,cmd):
27    'Run a command in a python image'
28    try:
29        err=None
30        p = subprocess.Popen([image,'-c',cmd],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
31        out = p.stdout.read()
32        err = p.stderr.read()
33        p.communicate()
34        return out,err
35    except Exception(err):
36        return '','Exception = '+err
37
38project="GSAS-II"
39AppleScript = ''
40'''Contains an AppleScript to start GSAS-II launching python and the
41GSAS-II python script
42'''
43
44if __name__ == '__main__': AppleScript += '''(*   GSAS-II AppleScript by B. Toby (brian.toby@anl.gov)
45     It can launch GSAS-II by double clicking or by dropping a data file
46     or folder over the app.
47     It runs GSAS-II in a terminal window.
48*)
49
50(* test if a file is present and exit with an error message if it is not  *)
51on TestFilePresent(appwithpath)
52        tell application "System Events"
53                if (file appwithpath exists) then
54                else
55                        display dialog "Error: file " & appwithpath & " not found. If you have moved this file recreate the AppleScript with bootstrap.py." with icon caution buttons {{"Quit"}}
56                        return
57                end if
58        end tell
59end TestFilePresent
60
61(*
62------------------------------------------------------------------------
63this section responds to a double-click. No file is supplied to GSAS-II
64------------------------------------------------------------------------
65*)
66on run
67        set python to "{:s}"
68        set appwithpath to "{:s}"
69        set env to "{:s}"
70        TestFilePresent(appwithpath)
71        TestFilePresent(python)
72        tell application "Terminal"
73                activate
74                do script env & python & " " & appwithpath & "; exit"
75        end tell
76end run
77
78(*
79-----------------------------------------------------------------------------------------------
80this section handles starting with files dragged into the AppleScript
81 o it goes through the list of file(s) dragged in
82 o then it converts the colon-delimited macintosh file location to a POSIX filename
83 o for every non-directory file dragged into the icon, it starts GSAS-II, passing the file name
84------------------------------------------------------------------------------------------------
85*)
86
87on open names
88        set python to "{:s}"
89        set appwithpath to "{:s}"
90        set env to "{:s}"
91 
92        TestFilePresent(appwithpath)
93        repeat with filename in names
94                set filestr to (filename as string)
95                if filestr ends with ":" then
96                        (* should not happen, skip directories *)
97                else
98                        (* if this is an input file, open it *)
99                        set filename to the quoted form of the POSIX path of filename
100                        tell application "Terminal"
101                                activate
102                                do script env & python & " " & appwithpath & " " & filename & "; exit"
103                        end tell
104                end if
105        end repeat
106end open
107'''
108
109if __name__ == '__main__':
110    # find the main GSAS-II script if not on command line
111    if len(sys.argv) == 1:
112        script = os.path.abspath(os.path.join(
113            os.path.split(__file__)[0],
114            "GSASII.py"
115            ))
116    elif len(sys.argv) == 2:
117        script = os.path.abspath(sys.argv[1])
118    else:
119        Usage()
120
121    # make sure we found it
122    if not os.path.exists(script):
123        print("\nFile "+script+" not found")
124        Usage()
125    if os.path.splitext(script)[1].lower() != '.py':
126        print("\nScript "+script+" does not have extension .py")
127        Usage()
128    # where the app will be created
129    scriptdir = os.path.split(script)[0]
130    # name of app
131    apppath = os.path.abspath(os.path.join(scriptdir,project+".app"))
132    iconfile = os.path.join(scriptdir,'gsas2.icns') # optional icon file
133
134    # find the python application; must be an OS X app
135    pythonpath = os.path.realpath(sys.executable)
136    top = True
137    while top:
138        pythonapp = os.path.join(pythonpath,'Resources','Python.app','Contents','MacOS','Python')
139        if os.path.exists(pythonapp): break
140        pythonpath,top = os.path.split(pythonpath)
141    else:
142        #print("\nSorry, failed to find a Resources directory associated with "+str(sys.executable))
143        pythonapp = sys.executable
144   
145    # create a link to the python app, but named to match the project
146    if os.path.exists('/tmp/testpython'): os.remove('/tmp/testpython')
147    os.symlink(pythonapp,'/tmp/testpython')
148    # test if it runs
149    testout,errout = RunPython('/tmp/testpython','import numpy; import wx; print("OK")')
150    os.remove('/tmp/testpython')
151    #print testout,errout
152    if testout.strip() != "OK":
153        print('Run of wx in python failed, looking for pythonw')
154        pythonapp = os.path.join(os.path.split(sys.executable)[0],'pythonw')
155        if not os.path.exists(pythonapp):
156            raise Exception('no pythonw found with '+sys.executable)
157        newpython = pythonapp
158    else:
159        # new name to call python
160        newpython =  os.path.join(apppath,"Contents","MacOS",project)
161
162    if os.path.exists(apppath): # cleanup
163        print("\nRemoving old "+project+" app ("+str(apppath)+")")
164        shutil.rmtree(apppath)
165
166    shell = os.path.join("/tmp/","appscrpt.script")
167    f = open(shell, "w")
168    f.write(AppleScript.format(newpython,script,'',newpython,script,''))
169    f.close()
170
171    try: 
172        subprocess.check_output(["osacompile","-o",apppath,shell],stderr=subprocess.STDOUT)
173    except subprocess.CalledProcessError as msg:
174        print('''Error compiling AppleScript.
175        Report the next message along with details about your Mac to toby@anl.gov''')
176        print(msg.output)
177        sys.exit()
178
179    # create a link to the python app, but named to match the project
180    if pythonapp != newpython: os.symlink(pythonapp,newpython)
181
182    # change the icon
183    oldicon = os.path.join(apppath,"Contents","Resources","droplet.icns")
184    if os.path.exists(iconfile) and os.path.exists(oldicon):
185        shutil.copyfile(iconfile,oldicon)
186
187    # Edit the app plist file to restrict the type of files that can be dropped
188    d = plistlib.readPlist(os.path.join(apppath,"Contents",'Info.plist'))
189    d['CFBundleDocumentTypes'] = [{
190        'CFBundleTypeExtensions': ['gpx'],
191        'CFBundleTypeName': 'GSAS-II project',
192        'CFBundleTypeRole': 'Editor'}]
193   
194    plistlib.writePlist(d,os.path.join(apppath,"Contents",'Info.plist'))
195
196    print("\nCreated "+project+" app ("+str(apppath)+
197          ").\nViewing app in Finder so you can drag it to the dock if, you wish.")
198    subprocess.call(["open","-R",apppath])
Note: See TracBrowser for help on using the repository browser.