source: install/g2complete/src/bootstrap.py @ 3930

Last change on this file since 3930 was 3930, checked in by toby, 5 years ago

more debugging of OSX packaging

  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 17.2 KB
Line 
1#!/usr/bin/env python
2# Installs GSAS-II from network using subversion and creates platform-specific shortcuts.
3# works for Mac & Linux & Windows
4from __future__ import division, print_function
5import os, stat, sys, platform, subprocess, datetime
6
7version = "$Id: bootstrap.py 3515 2018-07-30 02:14:14Z toby $"
8g2home = 'https://subversion.xray.aps.anl.gov/pyGSAS/'
9path2GSAS2 = os.path.dirname(os.path.abspath(os.path.expanduser(__file__)))
10
11skipInstallSteps = False
12skipDownloadSteps = False
13skipProxy = False
14help = False
15allBinaries = False
16for a in sys.argv[1:]:
17    if 'noinstall' in a.lower():
18        skipInstallSteps = True
19    elif 'nonet' in a.lower():
20        skipDownloadSteps = True
21        skipProxy = True
22    elif 'noproxy' in a.lower():
23        skipProxy = True
24    elif 'help' in a.lower():
25        help = True
26    elif 'allbin' in a.lower() or 'server' in a.lower():
27        allBinaries = True
28    else:
29        help = True
30
31if help:
32    print('''
33  bootstrap.py options:
34
35    --noinstall skip post-install, such as creating run shortcuts
36    --noproxy   do not ask for proxy information
37    --server    load all binary versions
38    --allbin    load all binary versions (same as --server)
39    --help      this message
40    --nonet     skip steps requiring internet
41
42''')
43    sys.exit()
44
45now = str(datetime.datetime.now())
46print('Running bootstrap from {} at {}\n\tId: {}'.format(path2GSAS2,now,version))
47fp = open(os.path.join(path2GSAS2,'bootstrap.log'),'a')
48fp.write('Running bootstrap from {} at {}\n\tId: {}\n'.format(path2GSAS2,now,version))
49fp.close()
50       
51################################################################################
52################################################################################
53def GetConfigValue(*args): return True
54# routines copied from GSASIIpath.py
55proxycmds = []
56'Used to hold proxy information for subversion, set if needed in whichsvn'
57svnLocCache = None
58'Cached location of svn to avoid multiple searches for it'
59
60def MakeByte2str(arg):
61    '''Convert output from subprocess pipes (bytes) to str (unicode) in Python 3.
62    In Python 2: Leaves output alone (already str).
63    Leaves stuff of other types alone (including unicode in Py2)
64    Works recursively for string-like stuff in nested loops and tuples.
65
66    typical use::
67
68        out = MakeByte2str(out)
69
70    or::
71
72        out,err = MakeByte2str(s.communicate())
73   
74    '''
75    if isinstance(arg,str): return arg
76    if isinstance(arg,bytes): return arg.decode()
77    if isinstance(arg,list):
78        return [MakeByte2str(i) for i in arg]
79    if isinstance(arg,tuple):
80        return tuple([MakeByte2str(i) for i in arg])
81    return arg
82
83def getsvnProxy():
84    '''Loads a proxy for subversion from the file created by bootstrap.py
85    '''
86    proxyinfo = os.path.join(path2GSAS2,"proxyinfo.txt")
87    if os.path.exists(proxyinfo):
88        global proxycmds
89        global host,port  # only in bootstrap.py
90        proxycmds = []
91        fp = open(proxyinfo,'r')
92        host = fp.readline().strip()
93        port = fp.readline().strip()
94        fp.close()
95        setsvnProxy(host,port)
96        if not host.strip(): return '',''
97        return host,port
98    return '',''
99
100def setsvnProxy(host,port):
101    '''Sets the svn commands needed to use a proxy
102    '''
103    global proxycmds
104    proxycmds = []
105    host = host.strip()
106    port = port.strip()
107    if not host.strip(): return
108    proxycmds.append('--config-option')
109    proxycmds.append('servers:global:http-proxy-host='+host)
110    if port.strip():
111        proxycmds.append('--config-option')
112        proxycmds.append('servers:global:http-proxy-port='+port)
113       
114def whichsvn():
115    '''Returns a path to the subversion exe file, if any is found.
116    Searches the current path after adding likely places where GSAS-II
117    might install svn.
118
119    :returns: None if svn is not found or an absolute path to the subversion
120      executable file.
121    '''
122    # use a previosuly cached svn location
123    global svnLocCache
124    if svnLocCache: return svnLocCache
125    # prepare to find svn
126    is_exe = lambda fpath: os.path.isfile(fpath) and os.access(fpath, os.X_OK)
127    svnprog = 'svn'
128    if sys.platform.startswith('win'): svnprog += '.exe'
129    host,port = getsvnProxy()
130    if GetConfigValue('debug') and host:
131        print('DBG_Using proxy host {} port {}'.format(host,port))
132    # add likely places to find subversion when installed with GSAS-II
133    pathlist = os.environ["PATH"].split(os.pathsep)
134    pathlist.insert(0,os.path.split(sys.executable)[0])
135    pathlist.insert(1,path2GSAS2)
136    for rpt in ('..','bin'),('..','Library','bin'),('svn','bin'),('svn',),('.'):
137        pt = os.path.normpath(os.path.join(path2GSAS2,*rpt))
138        if os.path.exists(pt):
139            pathlist.insert(0,pt)   
140    # search path for svn or svn.exe
141    for path in pathlist:
142        exe_file = os.path.join(path, svnprog)
143        if is_exe(exe_file):
144            try:
145                p = subprocess.Popen([exe_file,'help'],stdout=subprocess.PIPE)
146                res = p.stdout.read()
147                p.communicate()
148                svnLocCache = os.path.abspath(exe_file)
149                return svnLocCache
150            except:
151                pass       
152    svnLocCache = None
153
154def svnVersion(svn=None):
155    '''Get the version number of the current subversion executable
156
157    :returns: a string with a version number such as "1.6.6" or None if
158      subversion is not found.
159
160    '''
161    if not svn: svn = whichsvn()
162    if not svn: return
163
164    cmd = [svn,'--version','--quiet']
165    s = subprocess.Popen(cmd,
166                         stdout=subprocess.PIPE,stderr=subprocess.PIPE)
167    out,err = MakeByte2str(s.communicate())
168    if err:
169        print ('subversion error!\nout=%s'%out)
170        print ('err=%s'%err)
171        s = '\nsvn command:  '
172        for i in cmd: s += i + ' '
173        print(s)
174        return None
175    return out.strip()
176
177def svnVersionNumber(svn=None):
178    '''Get the version number of the current subversion executable
179
180    :returns: a fractional version number such as 1.6 or None if
181      subversion is not found.
182
183    '''
184    ver = svnVersion(svn)
185    if not ver: return 
186    M,m = ver.split('.')[:2]
187    return int(M)+int(m)/10.
188
189################################################################################
190################################################################################
191print(70*'*')
192#testing for incorrect locale code'
193try:
194    import locale
195    locale.getdefaultlocale()
196except ValueError:
197    print('Your location is not set properly. This causes problems for matplotlib')
198    print('  (see https://github.com/matplotlib/matplotlib/issues/5420.)')
199    print('Will try to bypass problem by setting LC_ALL to en_US.UTF-8 (US English)')
200    os.environ['LC_ALL'] = 'en_US.UTF-8'
201    locale.getdefaultlocale()
202print('Preloading matplotlib to build fonts...')
203try:
204    import matplotlib
205except:
206    pass
207print('Checking python packages...')
208missing = []
209for pkg in ['numpy','scipy','matplotlib','wx','OpenGL',]:
210    try:
211        exec('import '+pkg)
212    except:
213        missing.append(pkg)
214
215if missing and not skipInstallSteps:
216    msg = """Sorry, this version of Python cannot be used
217for GSAS-II. It is missing the following package(s):
218\t"""
219    for pkg in missing: msg += " "+pkg
220    print(msg)
221    print("\nPlease install these package(s) and try running this again.")
222    print("Showing first error: ")
223    for pkg in ['numpy','scipy','matplotlib','wx','OpenGL',]:
224        exec('import '+pkg)
225    sys.exit()
226
227if not skipDownloadSteps:
228    host = None
229    port = '80'
230    print('\nChecking for subversion...')
231    svn = whichsvn() # resets host & port if proxyinfo.txt is found
232    if not svn:
233        print("Sorry, subversion (svn) could not be found on your system.")
234        print("Please install this or place in path and rerun this.")
235        #raise Exception('Subversion (svn) not found')
236        sys.exit()
237    print(' found svn image: '+svn)
238
239#if install_with_easyinstall:           
240#    print('\nInstalling PyOpenGL. Lots of warnings will follow... ')
241#    install_with_easyinstall('PyOpenGl')               
242#    print('done.')
243   
244print('Ready to bootstrap GSAS-II from repository\n\t'+g2home+'\nto '+path2GSAS2)
245proxycmds = []
246proxyinfo = os.path.join(path2GSAS2,"proxyinfo.txt")
247if os.path.exists(proxyinfo):
248    fp = open(proxyinfo,'r')
249    host = fp.readline().strip()
250    port = fp.readline().strip()
251    fp.close()
252    os.remove(proxyinfo)
253print(70*"=")
254if sys.version_info[0] == 2:
255    getinput = raw_input
256else:
257    getinput = input
258
259# get proxy from environment variable
260key = None
261for i in os.environ.keys():
262    if 'https_proxy' == i.lower():
263        key = i
264        break
265else:
266    for i in os.environ.keys():
267        if 'http_proxy' == i.lower():
268            key = i
269            break
270val = ''
271if key:
272    print('key=',key)
273    val = os.environ[key].strip()
274    print('val=',val)
275if val:
276    if val[-1] == '/':
277        val = val[:-1]
278    if len(val.split(':')) > 2:
279        host = ':'.join(val.split(':')[:-1])
280        port = val.split(':')[-1]
281    else:
282        host = ':'.join(val.split(':')[:-1])
283        port = val.split(':')[-1]
284
285# get proxy from user, if terminal available
286try:
287    if skipProxy:
288        host = ""
289    elif host:
290        ans = getinput("Enter the proxy address (type none to remove) ["+host+"]: ").strip()
291        if ans.lower() == "none": host = ""
292    else:
293        ans = getinput("Enter your proxy address [none needed]: ").strip()
294        if ans: host = ans
295    if host:
296        ans = getinput("Enter the proxy port ["+port+"]: ").strip()
297        if ans == "": ans=port
298        port = ans
299except EOFError:
300    host = ""
301    port = ""
302if host:
303    proxycmds.append('--config-option')
304    proxycmds.append('servers:global:http-proxy-host='+host.strip())
305    if port:
306        proxycmds.append('--config-option')
307        proxycmds.append('servers:global:http-proxy-port='+port.strip())
308    fp = open(proxyinfo,'w')
309    fp.write(host.strip()+'\n')
310    fp.write(port.strip()+'\n')
311    fp.close()
312    fp = open(os.path.join(path2GSAS2,'bootstrap.log'),'a')
313    fp.write('Proxy info written: {} port\n'.format(host,port))
314    print('Proxy info written: {} port'.format(host,port))
315    fp.close()
316
317if not skipDownloadSteps:
318    # patch: switch GSAS-II location if linked to XOR server (relocated May/June 2017)
319    cmd = [svn, 'info']
320    p = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
321    res,err = p.communicate()
322    if '.xor.' in str(res):
323        print('Switching previous install with .xor. download location to\n\thttps://subversion.xray.aps.anl.gov/pyGSAS')
324        cmd = [svn, 'switch','--relocate','https://subversion.xor.aps.anl.gov/pyGSAS',
325               'https://subversion.xray.aps.anl.gov/pyGSAS']
326        if proxycmds: cmd += proxycmds
327        p = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
328        res,err = p.communicate()
329        if err:
330            print('Please report this error to toby@anl.gov:')
331            print(err)
332            print(res)
333    # patch: switch GSAS-II location if switched to 2frame version (removed August 2017)
334    if '2frame' in str(res):
335        print('Switching previous 2frame install to trunk\n\thttps://subversion.xray.aps.anl.gov/pyGSAS')
336        cmd = [svn, 'switch',g2home + '/trunk',path2GSAS2,
337               '--non-interactive','--trust-server-cert',
338               '--accept','theirs-conflict','--force','--ignore-ancestry']
339        if proxycmds: cmd += proxycmds
340        p = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
341        res,err = p.communicate()
342        if err:
343            print('Please report this error to toby@anl.gov:')
344            print(err)
345            print(res)
346
347    print('\n'+75*'*')
348    print('Now preparing to install GSAS-II')
349    tryagain = True
350    err = False
351    firstPass = 0
352    while(tryagain):
353        tryagain = False
354        if err:
355            print('Retrying after a cleanup...')
356            cmd = [svn, 'cleanup', path2GSAS2]
357            s = subprocess.Popen(cmd,stderr=subprocess.PIPE)
358            out,err = s.communicate()   
359            if err:
360                print('subversion returned an error:')
361                print(out)
362                print(err)
363        cmd = [svn, 'co', g2home+ 'trunk/', path2GSAS2, '--non-interactive', '--trust-server-cert']
364        if proxycmds: cmd += proxycmds
365        msg = 'svn load command: '
366        for item in cmd: msg += " "+item
367        print(msg)
368        s = subprocess.Popen(cmd,stderr=subprocess.PIPE)
369        print('\nsubversion output:')
370        out,err = s.communicate()
371        if err:
372            print('subversion returned an error:')
373            print(out)
374            print(err)
375            if firstPass == 0: tryagain = True
376        firstPass += 1
377    if err:
378        print('Retrying with a command for older svn version...')
379        cmd = [svn, 'co', g2home+ 'trunk/', path2GSAS2]
380        if proxycmds: cmd += proxycmds
381        msg = ""
382        for item in cmd: msg += " " + item
383        print(msg)
384        s = subprocess.Popen(cmd,stderr=subprocess.PIPE)
385        out,err = s.communicate()
386        if err:
387            print('subversion returned an error:')
388            print(err)
389            print('  *** GSAS-II failed to be installed. A likely reason is a network access')
390            print('  *** problem, most commonly because you need to use a network proxy. Please')
391            print('  *** check with a network administrator or use http://www.whatismyproxy.com/\n')
392            sys.exit()
393    print('\n'+75*'*')
394
395try:
396    import GSASIIpath
397    print('import of GSASIIpath completed')
398except Exception as err:
399    print('\n'+75*'=')
400    print('Failed with import of GSASIIpath. This is unexpected.')
401    print('GSAS-II will not run without correcting this. Contact toby@anl.gov')
402    print(err)
403    print(75*'=')
404    sys.exit()
405
406if allBinaries and skipDownloadSteps:
407    print('Loading all binaries with command...')
408    if not GSASIIpath.svnSwitchDir('AllBinaries','',g2home+ 'Binaries/',None,True):
409        print('Binary load failed')
410        sys.exit()
411else:
412    GSASIIpath.DownloadG2Binaries(g2home)
413       
414#===========================================================================
415# test if the compiled files load correctly
416#===========================================================================
417
418script = """  # commands that test each module can at least be loaded & run something in pyspg
419try:
420    import GSASIIpath
421    GSASIIpath.SetBinaryPath(loadBinary=False)
422    import pyspg
423    import histogram2d
424    import polymask
425    import pypowder
426    import pytexture
427    pyspg.sgforpy('P -1')
428    print('==OK==')
429except Exception as err:
430    print(err)
431"""
432p = subprocess.Popen([sys.executable,'-c',script],stdout=subprocess.PIPE,stderr=subprocess.PIPE,
433                     cwd=path2GSAS2)
434res,err = p.communicate()
435if '==OK==' not in str(res) or p.returncode != 0:
436    print('\n'+75*'=')
437    print('Failed when testing the GSAS-II compiled files. GSAS-II will not run')
438    print('without correcting this.\n\nError message:')
439    if res: 
440        print(res.decode())
441    if err:
442        print(err.decode())
443    #print('\nAttempting to open a web page on compiling GSAS-II...')
444    print('Please see web page\nhttps://subversion.xray.aps.anl.gov/trac/pyGSAS/wiki/CompileGSASII')
445    #import webbrowser
446    #webbrowser.open_new('https://subversion.xray.aps.anl.gov/trac/pyGSAS/wiki/CompileGSASII')
447    print(75*'=')
448#    if '86' in platform.machine() and (sys.platform.startswith('linux')
449#                                        or sys.platform == "darwin"
450#                                        or sys.platform.startswith('win')):
451#        print('Platform '+sys.platform+' with processor type '+platform.machine()+' is supported')
452#    else:
453#        print('Platform '+sys.platform+' with processor type '+platform.machine()+' not is supported')
454    sys.exit()
455else:
456    print('Successfully tested compiled routines')
457#===========================================================================
458# import all .py files so that .pyc files get created
459if not skipInstallSteps:
460    print('Byte-compiling all .py files...')
461    import compileall
462    compileall.compile_dir(path2GSAS2,quiet=True)
463    print('done')
464#===========================================================================
465# platform-dependent stuff
466#===========================================================================
467if sys.version_info[0] > 2:
468    def execfile(file):
469        with open(file) as source_file:
470            exec(source_file.read())
471
472if skipInstallSteps:
473    pass
474#===========================================================================
475# on Windows, make a batch file with Python and GSAS-II location hard-coded
476elif sys.platform.startswith('win') and os.path.exists(
477    os.path.join(path2GSAS2,"makeBat.py")):
478    execfile(os.path.join(path2GSAS2,"makeBat.py"))
479#===========================================================================
480# on a Mac, make an applescript
481elif sys.platform.startswith('darwin') and os.path.exists(
482    os.path.join(path2GSAS2,"makeMacApp.py")):
483    sys.argv = [os.path.join(path2GSAS2,"makeMacApp.py")]
484    print(u'running '+sys.argv[0])
485    execfile(sys.argv[0])
486#===========================================================================
487# On linux, make desktop icon
488elif sys.platform.startswith('linux') and os.path.exists(
489    os.path.join(path2GSAS2,"makeLinux.py")):
490    sys.argv = [os.path.join(path2GSAS2,"makeLinux.py")]
491    print(u'running '+sys.argv[0])
492    execfile(sys.argv[0])
493
Note: See TracBrowser for help on using the repository browser.