source: sasview/installers/installer_generator.py @ 9a0fc50

magnetic_scattrelease-4.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249unittest-saveload
Last change on this file since 9a0fc50 was a0f4768, checked in by Piotr Rozyczko <rozyczko@…>, 7 years ago

Added a conditional for 32-bit installers

  • Property mode set to 100644
File size: 16.0 KB
Line 
1"""
2This module generates .iss file according to the local config of
3the current application. Please make sure a file named "local_config.py"
4exists in the current directory. Edit local_config.py according to your needs.
5"""
6from __future__ import print_function
7
8import os
9import sys
10import string
11
12is_64bit = sys.maxsize > 2**32
13
14root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
15sys.path.insert(0, os.path.join(root, 'sasview-install', 'Lib', 'site-packages'))
16from sas.sasview import local_config
17
18#REG_PROGRAM = """{app}\MYPROG.EXE"" ""%1"""
19APPLICATION = str(local_config.__appname__ )+ '.exe'
20AppName = str(local_config.__appname__ )
21AppVerName = str(local_config.__appname__ )+'-'+ str(local_config.__version__)
22Dev = ''
23if AppVerName.lower().count('dev') > 0:
24    Dev = '-Dev'
25AppPublisher = local_config._copyright
26AppPublisherURL = local_config._homepage
27AppSupportURL = local_config._homepage
28AppUpdatesURL = local_config._homepage
29ArchitecturesInstallIn64BitMode = 'x64'
30ChangesEnvironment = 'true'
31DefaultDirName = os.path.join("{pf}" , AppName+Dev)
32DefaultGroupName = os.path.join(local_config.DefaultGroupName, AppVerName)
33
34OutputBaseFilename = local_config.OutputBaseFilename
35SetupIconFile = local_config.SetupIconFile_win
36LicenseFile = 'license.txt'
37DisableProgramGroupPage = 'yes'
38Compression = 'lzma'
39SolidCompression = 'yes'
40PrivilegesRequired = 'none'
41INSTALLER_FILE = 'installer'
42
43icon_path =  local_config.icon_path
44media_path = local_config.media_path
45test_path = local_config.test_path
46
47def find_extension():
48    """
49    Describe the extensions that can be read by the current application
50    """
51    list_data = []
52    list_app =[]
53    try:
54
55        #(ext, type, name, flags)
56        from sas.sascalc.dataloader.loader import Loader
57        wild_cards = Loader().get_wildcards()
58        for item in wild_cards:
59            #['All (*.*)|*.*']
60            file_type, ext = string.split(item, "|*", 1)
61            if ext.strip() not in ['.*', ''] and ext.strip() not in list_data:
62                list_data.append((ext, 'string', file_type))
63    except Exception:
64        pass
65    try:
66        file_type, ext = string.split(local_config.APPLICATION_WLIST, "|*", 1)
67        if ext.strip() not in ['.', ''] and ext.strip() not in list_app:
68            list_app.append((ext, 'string', file_type))
69    except Exception:
70        pass
71    try:
72        for item in local_config.PLUGINS_WLIST:
73            file_type, ext = string.split(item, "|*", 1)
74            if ext.strip() not in ['.', ''] and ext.strip() not in list_app:
75                list_app.append((ext, 'string', file_type))
76    except Exception:
77        pass
78    return list_data, list_app
79DATA_EXTENSION, APP_EXTENSION = find_extension()
80
81def write_registry(data_extension=None, app_extension=None):
82    """
83    create file association for windows.
84    Allow open file on double click
85    """
86    msg = ""
87    if data_extension is not None and data_extension:
88        openwithlist = "OpenWithList\%s" % str(APPLICATION)
89        msg = "\n\n[Registry]\n"
90        for (ext, type, _) in data_extension:
91            list = os.path.join(ext, openwithlist)
92            msg +=  """Root: HKCR;\tSubkey: "%s";\t""" % str(list)
93            msg += """ Flags: %s""" % str('uninsdeletekey noerror')
94            msg += "\n"
95        #list the file on right-click
96        msg += """Root: HKCR; Subkey: "applications\%s\shell\open\command";\t"""\
97                              %  str(APPLICATION)
98        msg += """ValueType: %s; """ % str('string')
99        msg += """ValueName: "%s";\t""" %str('')
100        msg += """ValueData: \"""{app}\%s""  ""%s1\"""; \t"""% (str(APPLICATION),
101                                                          str('%'))
102        msg += """ Flags: %s""" % str('uninsdeletevalue noerror')
103        msg += "\n"
104        user_list = "Software\Classes"
105        for (ext, type, _) in data_extension:
106            list = os.path.join(user_list, ext, openwithlist)
107            msg +=  """Root: HKCU;\tSubkey: "%s";\t""" % str(list)
108            msg += """ Flags: %s""" % str('uninsdeletekey noerror')
109            msg += "\n"
110        #list the file on right-click
111        user_list = os.path.join("Software", "Classes", "applications")
112        msg += """Root: HKCU; Subkey: "%s\%s\shell\open\command";\t"""\
113                              %  (str(user_list), str(APPLICATION))
114        msg += """ValueType: %s; """ % str('string')
115        msg += """ValueName: "%s";\t""" %str('')
116        msg += """ValueData: \"""{app}\%s""  ""%s1\"""; \t"""% (str(APPLICATION),
117                                                          str('%'))
118        msg += """ Flags: %s""" % str('uninsdeletevalue noerror')
119        msg += "\n"
120    if app_extension is not None and app_extension:
121        for (ext, type, _) in app_extension:
122            msg +=  """Root: HKCR;\tSubkey: "%s";\t""" % str(ext)
123            msg += """ValueType: %s;\t""" % str(type)
124            #file type empty set the current application as the default
125            #reader for this file. change the value of file_type to another
126            #string modify the default reader
127            file_type = ''
128            msg += """ValueName: "%s";\t""" % str('')
129            msg += """ValueData: "{app}\%s";\t""" % str(APPLICATION)
130            msg += """ Flags: %s""" % str('uninsdeletevalue  noerror')
131            msg += "\n"
132    msg += """Root: HKCR; Subkey: "{app}\%s";\t""" % str(APPLICATION)
133    msg += """ValueType: %s; """ % str('string')
134    msg += """ValueName: "%s";\t""" % str('')
135    msg += """ValueData: "{app}\%s";\t""" % str("SasView File")
136    msg += """ Flags: %s \t""" % str("uninsdeletekey  noerror")
137    msg += "\n"
138
139    #execute the file on double-click
140    msg += """Root: HKCR; Subkey: "{app}\%s\shell\open\command";\t"""  %  str(APPLICATION)
141    msg += """ValueType: %s; """ % str('string')
142    msg += """ValueName: "%s";\t""" %str('')
143    msg += """ValueData: \"""{app}\%s""  ""%s1\""";\t"""% (str(APPLICATION),
144                                                          str('%'))
145    msg += """ Flags: %s \t""" % str("uninsdeletevalue noerror")
146    msg += "\n"
147    #create default icon
148    msg += """Root: HKCR; Subkey: "{app}\%s";\t""" % str(SetupIconFile)
149    msg += """ValueType: %s; """ % str('string')
150    msg += """ValueName: "%s";\t""" % str('')
151    msg += """ValueData: "{app}\%s,0";\t""" % str(APPLICATION)
152    msg += """ Flags: %s \t""" % str("uninsdeletevalue noerror")
153    msg += "\n"
154
155
156    #SASVIEWPATH
157    msg += """Root: HKLM; Subkey: "%s";\t"""  %  str('SYSTEM\CurrentControlSet\Control\Session Manager\Environment')
158    msg += """ValueType: %s; """ % str('expandsz')
159    msg += """ValueName: "%s";\t""" % str('SASVIEWPATH')
160    msg += """ValueData: "{app}";\t"""
161    msg += """ Flags: %s""" % str('uninsdeletevalue noerror')
162    msg += "\n"
163
164    #PATH
165    msg += """; Write to PATH (below) is disabled; need more tests\n"""
166    msg += """;Root: HKCU; Subkey: "%s";\t"""  %  str('Environment')
167    msg += """ValueType: %s; """ % str('expandsz')
168    msg += """ValueName: "%s";\t""" % str('PATH')
169    msg += """ValueData: "%s;{olddata}";\t""" % str('%SASVIEWPATH%')
170    msg += """ Check: %s""" % str('NeedsAddPath()')
171    msg += "\n"
172
173    return msg
174
175def write_languages(languages=('english',), msfile="compiler:Default.isl"):
176    """
177    define the language of the application
178    """
179    msg = ''
180    if languages:
181        msg = "\n\n[Languages]\n"
182        for lang in languages:
183            msg += """Name: "%s";\tMessagesFile: "%s"\n""" % (str(lang), str(msfile))
184    return msg
185
186def write_tasks():
187    """
188    create desktop icon
189    """
190    msg = """\n\n[Tasks]\n"""
191    msg += """Name: "desktopicon";\tDescription: "{cm:CreateDesktopIcon}";\t"""
192    msg += """GroupDescription: "{cm:AdditionalIcons}";\tFlags: unchecked\n"""
193    msg += """Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}";\t"""
194    msg += """GroupDescription: "{cm:AdditionalIcons}";\n"""
195    return msg
196
197dist_path = "dist"
198def write_file():
199    """
200    copy some data files
201    """
202    msg = "\n\n[Files]\n"
203    msg += """Source: "%s\%s";\t""" % (dist_path, str(APPLICATION))
204    msg += """DestDir: "{app}";\tFlags: ignoreversion\n"""
205    msg += """Source: "dist\*";\tDestDir: "{app}";\t"""
206    msg += """Flags: ignoreversion recursesubdirs createallsubdirs\n"""
207    msg += """Source: "dist\plugin_models\*";\tDestDir: "{userdesktop}\..\.sasview\plugin_models";\t"""
208    msg += """Flags: recursesubdirs createallsubdirs\n"""
209    msg += """Source: "dist\compiled_models\*";\tDestDir: "{userdesktop}\..\.sasmodels\compiled_models";\t"""
210    msg += """Flags: recursesubdirs createallsubdirs\n"""
211    msg += """Source: "dist\config\custom_config.py";\tDestDir: "{userdesktop}\..\.sasview\config";\t"""
212    msg += """Flags: recursesubdirs createallsubdirs\n"""
213    #msg += """Source: "dist\default_categories.json";    DestDir: "{userdesktop}\..\.sasview";\t"""
214    #msg += """DestName: "categories.json";\n"""
215    msg += """;\tNOTE: Don't use "Flags: ignoreversion" on any shared system files"""
216    return msg
217
218def write_icon():
219    """
220    Create application icon
221    """
222    msg = """\n\n[Icons]\n"""
223    msg += """Name: "{group}\%s";\t""" % str(AppName)
224    msg += """Filename: "{app}\%s";\t"""  % str(APPLICATION)
225    msg += """WorkingDir: "{app}"; IconFilename: "{app}\images\\ball.ico" \n"""
226    msg += """Name: "{group}\{cm:UninstallProgram, %s}";\t""" % str(AppName)
227    msg += """ Filename: "{uninstallexe}" \n"""
228    msg += """Name: "{commondesktop}\%s";\t""" % str(AppVerName)
229    msg += """Filename: "{app}\%s";\t""" % str(APPLICATION)
230    msg += """Tasks: desktopicon; WorkingDir: "{app}" ; IconFilename: "{app}\images\\ball.ico" \n"""
231    msg += """Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\%s";\t""" % str(AppVerName)
232    msg += """Filename: "{app}\%s";\t""" % str(APPLICATION)
233    msg += """Tasks: quicklaunchicon; WorkingDir: "{app}"; IconFilename: "{app}\images\\ball.ico" \n"""
234    return msg
235
236def write_run():
237    """
238    execute some file
239    """
240    msg = """\n\n[Run]\n"""
241    msg += """Filename: "{app}\%s";\t""" % str(APPLICATION)
242    msg += """Description: "{cm:LaunchProgram, %s}";\t""" %str(AppName)
243    msg += """Flags: nowait postinstall skipifsilent\n"""
244    msg += """; Install the Microsoft C++ DLL redistributable package if it is """
245    msg += """provided and the DLLs are not present on the target system.\n"""
246    msg += """; Note that the redistributable package is included if the app was """
247    msg += """built using Python 2.6 or 2.7, but not with 2.5.\n"""
248    msg += """; Parameter options:\n"""
249    msg += """; - for silent install use: "/q"\n"""
250    msg += """; - for silent install with progress bar use: "/qb"\n"""
251    msg += """; - for silent install with progress bar but disallow """
252    msg += """cancellation of operation use: "/qb!"\n"""
253    msg += """; Note that we do not use the postinstall flag as this would """
254    msg += """display a checkbox and thus require the user to decide what to do.\n"""
255    msg += """;Filename: "{app}\\vcredist_x86.exe"; Parameters: "/qb!"; """
256    msg += """WorkingDir: "{tmp}"; StatusMsg: "Installing Microsoft Visual """
257    msg += """C++ 2008 Redistributable Package ..."; Check: InstallVC90CRT(); """
258    msg += """Flags: skipifdoesntexist waituntilterminated\n"""
259    return msg
260
261def write_dirs():
262    """
263    Define Dir permission
264    """
265    msg = """\n\n[Dirs]\n"""
266    msg += """Name: "{app}\%s";\t""" % str('')
267    msg += """Permissions: everyone-modify\t"""
268    msg += """\n"""
269    return msg
270
271def write_code():
272    """
273    Code that checks the existing path and snaviewpath
274    in the environmental viriables/PATH
275    """
276    msg = """\n\n[Code]\n"""
277    msg += """function InstallVC90CRT(): Boolean;\n"""
278    msg += """begin\n"""
279    msg += """    Result := not DirExists('C:\WINDOWS\WinSxS\\x86_Microsoft.VC90."""
280    msg += """CRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_d08d0375');\n"""
281    msg += """end;\n\n"""
282    msg += """function NeedsAddPath(): boolean;\n"""
283    msg += """var\n"""
284    msg += """  oldpath: string;\n"""
285    msg += """  newpath: string;\n"""
286    msg += """  pathArr:    TArrayOfString;\n"""
287    msg += """  i:        Integer;\n"""
288    msg += """begin\n"""
289    msg += """  RegQueryStringValue(HKEY_CURRENT_USER,'Environment',"""
290    msg += """'PATH', oldpath)\n"""
291    msg += """  oldpath := oldpath + ';';\n"""
292    msg += """  newpath := '%SASVIEWPATH%';\n"""
293    msg += """  i := 0;\n"""
294    msg += """  while (Pos(';', oldpath) > 0) do begin\n"""
295    msg += """    SetArrayLength(pathArr, i+1);\n"""
296    msg += """    pathArr[i] := Copy(oldpath, 0, Pos(';', oldpath)-1);\n"""
297    msg += """    oldpath := Copy(oldpath, Pos(';', oldpath)+1,"""
298    msg += """ Length(oldpath));\n"""
299    msg += """    i := i + 1;\n"""
300    msg += """    // Check if current directory matches app dir\n"""
301    msg += """    if newpath = pathArr[i-1] \n"""
302    msg += """    then begin\n"""
303    msg += """      Result := False;\n"""
304    msg += """      exit;\n"""
305    msg += """    end;\n"""
306    msg += """  end;\n"""
307    msg += """  Result := True;\n"""
308    msg += """end;\n"""
309    msg += """\n"""
310    return msg
311
312def write_uninstalldelete():
313    """
314    Define uninstalldelete
315    """
316    msg = """\n[UninstallDelete]\n"""
317    msg += """; Delete directories and files that are dynamically created by """
318    msg += """the application (i.e. at runtime).\n"""
319    msg += """Type: filesandordirs; Name: "{app}\.matplotlib"\n"""
320    msg += """Type: files; Name: "{app}\*.*"\n"""
321    msg += """; The following is a workaround for the case where the """
322    msg += """application is installed and uninstalled but the\n"""
323    msg += """;{app} directory is not deleted because it has user files.  """
324    msg += """Then the application is installed into the\n"""
325    msg += """; existing directory, user files are deleted, and the """
326    msg += """application is un-installed again.  Without the\n"""
327    msg += """; directive below, {app} will not be deleted because Inno Setup """
328    msg += """did not create it during the previous\n"""
329    msg += """; installation.\n"""
330    msg += """Type: dirifempty; Name: "{app}"\n"""
331    msg += """\n"""
332    return msg
333
334def generate_installer():
335    """
336    """
337    TEMPLATE = "\n; Script generated by the Inno Setup Script Wizard\n"
338    TEMPLATE += "\n; and local_config.py located in this directory.\n "
339    TEMPLATE += "; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!"
340    TEMPLATE += "\n[Setup]\n\n"
341    TEMPLATE += "ChangesAssociations=%s\n" %str('yes')
342    TEMPLATE += "AppName=%s\n" % str(AppName)
343    TEMPLATE += "AppVerName=%s\n" % str(AppVerName)
344    TEMPLATE += "AppPublisher=%s\n" % str(AppPublisher)
345    TEMPLATE += "AppPublisherURL=%s\n" % str(AppPublisherURL)
346    TEMPLATE += "AppSupportURL=%s\n" % str(AppSupportURL)
347    TEMPLATE += "AppUpdatesURL=%s \n" % str(AppUpdatesURL)
348    if is_64bit:
349        TEMPLATE += "ArchitecturesInstallIn64BitMode=%s \n" % str(ArchitecturesInstallIn64BitMode)
350    TEMPLATE += "ChangesEnvironment=%s \n" % str(ChangesEnvironment)
351    TEMPLATE += "DefaultDirName=%s\n" % str(DefaultDirName)
352    TEMPLATE += "DefaultGroupName=%s\n" % str(DefaultGroupName)
353    TEMPLATE += "DisableProgramGroupPage=%s\n" % str(DisableProgramGroupPage)
354    TEMPLATE += "LicenseFile=%s\n" % str(LicenseFile)
355    TEMPLATE += "OutputBaseFilename=%s\n" % str(OutputBaseFilename)
356    TEMPLATE += "SetupIconFile=%s\n" % str(SetupIconFile)
357    TEMPLATE += "Compression=%s\n" % str(Compression)
358    TEMPLATE += "SolidCompression=%s\n" % str(SolidCompression)
359    TEMPLATE += "PrivilegesRequired=%s\n" % str(PrivilegesRequired)
360    TEMPLATE += "UsePreviousAppDir=no\n"
361
362    TEMPLATE += write_registry(data_extension=DATA_EXTENSION,
363                                app_extension=APP_EXTENSION)
364    TEMPLATE += write_languages()
365    TEMPLATE += write_tasks()
366    TEMPLATE += write_file()
367    TEMPLATE += write_icon()
368    TEMPLATE += write_run()
369    TEMPLATE += write_dirs()
370    TEMPLATE += write_code()
371    TEMPLATE += write_uninstalldelete()
372    path = '%s.iss' % str(INSTALLER_FILE)
373    f = open(path,'w')
374    f.write(TEMPLATE)
375    f.close()
376    print("Generate Inno setup installer script complete")
377    print("A new file %s.iss should be created.Please refresh your directory" % str(INSTALLER_FILE))
378
379if __name__ == "__main__":
380    generate_installer()
Note: See TracBrowser for help on using the repository browser.