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