source: trunk/makeMacApp.py @ 1357

Last change on this file since 1357 was 1357, checked in by toby, 8 years ago

more 64-bit stuff; fix OS X install

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 7.5 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
44AppleScript += '''(*   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 python app failed, resorting to non-app version of Python, Alas!'
154        pythonapp = sys.executable
155        # is this brain-dead Canopy 1.4.0, if so, switch to pythonw
156        try:
157            import canopy.version
158            if canopy.version.version == '1.4.0':
159                print 'using pythonw for Canopy 1.4.0'
160                pythonapp = os.path.join(os.path.split(pythonapp)[0],'pythonw')
161                if not os.path.exists(pythonapp):
162                    raise Exception('no pythonw here: '+pythonapp)
163        except ImportError:
164            pass
165        newpython = pythonapp
166    else:
167        # new name to call python
168        newpython =  os.path.join(apppath,"Contents","MacOS",project)
169
170    if os.path.exists(apppath): # cleanup
171        print("\nRemoving old "+project+" app ("+str(apppath)+")")
172        shutil.rmtree(apppath)
173
174    shell = os.path.join("/tmp/","appscrpt.script")
175    f = open(shell, "w")
176    f.write(AppleScript.format(newpython,script,'',newpython,script,''))
177    f.close()
178
179    try: 
180        subprocess.check_output(["osacompile","-o",apppath,shell],stderr=subprocess.STDOUT)
181    except subprocess.CalledProcessError, msg:
182        print '''Error compiling AppleScript.
183        Report the next message along with details about your Mac to toby@anl.gov'''
184        print msg.output
185        sys.exit()
186
187    # create a link to the python app, but named to match the project
188    if pythonapp != newpython: os.symlink(pythonapp,newpython)
189
190    # change the icon
191    oldicon = os.path.join(apppath,"Contents","Resources","droplet.icns")
192    if os.path.exists(iconfile) and os.path.exists(oldicon):
193        shutil.copyfile(iconfile,oldicon)
194
195    # Edit the app plist file to restrict the type of files that can be dropped
196    d = plistlib.readPlist(os.path.join(apppath,"Contents",'Info.plist'))
197    d['CFBundleDocumentTypes'] = [{
198        'CFBundleTypeExtensions': ['gpx'],
199        'CFBundleTypeName': 'GSAS-II project',
200        'CFBundleTypeRole': 'Editor'}]
201   
202    plistlib.writePlist(d,os.path.join(apppath,"Contents",'Info.plist'))
203
204    print("\nCreated "+project+" app ("+str(apppath)+
205          ").\nViewing app in Finder so you can drag it to the dock if, you wish.")
206    subprocess.call(["open","-R",apppath])
Note: See TracBrowser for help on using the repository browser.