source: install/bootstrap.py @ 4235

Last change on this file since 4235 was 3910, checked in by toby, 3 years ago

new packaging including GSAS-II files

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 18.3 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 3910 2019-04-19 18:02:23Z 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:
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',]:
224        exec('import '+pkg)
225    sys.exit()
226# try:
227#     import OpenGL
228#     install_with_easyinstall = None
229# except:
230#     try:               
231#           from setuptools.command import easy_install                 
232#     except ImportError:
233#         print('You are missing the OpenGL Python package. This can be ')
234#         print('installed by this script if the setuptools package is installed')
235#         print('Please install either OpenGL (pyopengl) or setuptools')
236#         print("package and try running this again.")
237#         sys.exit()
238#     print("Missing the OpenGL Python package. Will attempt to install this later.")
239#     def install_with_easyinstall(package):             
240#         try:                   
241#             print("trying system-wide ")               
242#             easy_install.main(['-f',os.path.split(__file__)[0],package])               
243#             return             
244#         except:               
245#             pass               
246#         try:                   
247#             print("trying user level ")               
248#             easy_install.main(['-f',os.path.split(__file__)[0],'--user',package])             
249#             return             
250#         except:               
251#             print("\nInstall of "+package+" failed. Error traceback follows:")
252#             import traceback                   
253#             print(traceback.format_exc())
254#             sys.exit()
255
256if not skipDownloadSteps:
257    host = None
258    port = '80'
259    print('\nChecking for subversion...')
260    svn = whichsvn() # resets host & port if proxyinfo.txt is found
261    if not svn:
262        print("Sorry, subversion (svn) could not be found on your system.")
263        print("Please install this or place in path and rerun this.")
264        #raise Exception('Subversion (svn) not found')
265        sys.exit()
266    print(' found svn image: '+svn)
267
268#if install_with_easyinstall:           
269#    print('\nInstalling PyOpenGL. Lots of warnings will follow... ')
270#    install_with_easyinstall('PyOpenGl')               
271#    print('done.')
272   
273print('Ready to bootstrap GSAS-II from repository\n\t'+g2home+'\nto '+path2GSAS2)
274proxycmds = []
275proxyinfo = os.path.join(path2GSAS2,"proxyinfo.txt")
276if os.path.exists(proxyinfo):
277    fp = open(proxyinfo,'r')
278    host = fp.readline().strip()
279    port = fp.readline().strip()
280    fp.close()
281    os.remove(proxyinfo)
282print(70*"=")
283if sys.version_info[0] == 2:
284    getinput = raw_input
285else:
286    getinput = input
287
288# get proxy from environment variable
289key = None
290for i in os.environ.keys():
291    if 'https_proxy' == i.lower():
292        key = i
293        break
294else:
295    for i in os.environ.keys():
296        if 'http_proxy' == i.lower():
297            key = i
298            break
299if key:
300    val = os.environ[key].strip()
301    if val[-1] == '/':
302        val = val[:-1]
303    if len(val.split(':')) > 2:
304        host = ':'.join(val.split(':')[:-1])
305        port = val.split(':')[-1]
306    else:
307        host = ':'.join(val.split(':')[:-1])
308        port = val.split(':')[-1]
309
310# get proxy from user, if terminal available
311try:
312    if skipProxy:
313        host = ""
314    elif host:
315        ans = getinput("Enter the proxy address (type none to remove) ["+host+"]: ").strip()
316        if ans.lower() == "none": host = ""
317    else:
318        ans = getinput("Enter your proxy address [none needed]: ").strip()
319        if ans: host = ans
320    if host:
321        ans = getinput("Enter the proxy port ["+port+"]: ").strip()
322        if ans == "": ans=port
323        port = ans
324except EOFError:
325    host = ""
326    port = ""
327if host:
328    proxycmds.append('--config-option')
329    proxycmds.append('servers:global:http-proxy-host='+host.strip())
330    if port:
331        proxycmds.append('--config-option')
332        proxycmds.append('servers:global:http-proxy-port='+port.strip())
333    fp = open(proxyinfo,'w')
334    fp.write(host.strip()+'\n')
335    fp.write(port.strip()+'\n')
336    fp.close()
337    fp = open(os.path.join(path2GSAS2,'bootstrap.log'),'a')
338    fp.write('Proxy info written: {} port\n'.format(host,port))
339    print('Proxy info written: {} port'.format(host,port))
340    fp.close()
341
342if not skipDownloadSteps:
343    # patch: switch GSAS-II location if linked to XOR server (relocated May/June 2017)
344    cmd = [svn, 'info']
345    p = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
346    res,err = p.communicate()
347    if '.xor.' in str(res):
348        print('Switching previous install with .xor. download location to\n\thttps://subversion.xray.aps.anl.gov/pyGSAS')
349        cmd = [svn, 'switch','--relocate','https://subversion.xor.aps.anl.gov/pyGSAS',
350               'https://subversion.xray.aps.anl.gov/pyGSAS']
351        if proxycmds: cmd += proxycmds
352        p = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
353        res,err = p.communicate()
354        if err:
355            print('Please report this error to toby@anl.gov:')
356            print(err)
357            print(res)
358    # patch: switch GSAS-II location if switched to 2frame version (removed August 2017)
359    if '2frame' in str(res):
360        print('Switching previous 2frame install to trunk\n\thttps://subversion.xray.aps.anl.gov/pyGSAS')
361        cmd = [svn, 'switch',g2home + '/trunk',path2GSAS2,
362               '--non-interactive','--trust-server-cert',
363               '--accept','theirs-conflict','--force','--ignore-ancestry']
364        if proxycmds: cmd += proxycmds
365        p = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
366        res,err = p.communicate()
367        if err:
368            print('Please report this error to toby@anl.gov:')
369            print(err)
370            print(res)
371
372    print('\n'+75*'*')
373    print('Now preparing to install GSAS-II')
374    tryagain = True
375    err = False
376    firstPass = 0
377    while(tryagain):
378        tryagain = False
379        if err:
380            print('Retrying after a cleanup...')
381            cmd = [svn, 'cleanup', path2GSAS2]
382            s = subprocess.Popen(cmd,stderr=subprocess.PIPE)
383            out,err = s.communicate()   
384            if err:
385                print('subversion returned an error:')
386                print(out)
387                print(err)
388        cmd = [svn, 'co', g2home+ 'trunk/', path2GSAS2, '--non-interactive', '--trust-server-cert']
389        if proxycmds: cmd += proxycmds
390        msg = 'svn load command: '
391        for item in cmd: msg += " "+item
392        print(msg)
393        s = subprocess.Popen(cmd,stderr=subprocess.PIPE)
394        print('\nsubversion output:')
395        out,err = s.communicate()
396        if err:
397            print('subversion returned an error:')
398            print(out)
399            print(err)
400            if firstPass == 0: tryagain = True
401        firstPass += 1
402    if err:
403        print('Retrying with a command for older svn version...')
404        cmd = [svn, 'co', g2home+ 'trunk/', path2GSAS2]
405        if proxycmds: cmd += proxycmds
406        msg = ""
407        for item in cmd: msg += " " + item
408        print(msg)
409        s = subprocess.Popen(cmd,stderr=subprocess.PIPE)
410        out,err = s.communicate()
411        if err:
412            print('subversion returned an error:')
413            print(err)
414            print('  *** GSAS-II failed to be installed. A likely reason is a network access')
415            print('  *** problem, most commonly because you need to use a network proxy. Please')
416            print('  *** check with a network administrator or use http://www.whatismyproxy.com/\n')
417            sys.exit()
418    print('\n'+75*'*')
419
420try:
421    import GSASIIpath
422    print('import of GSASIIpath completed')
423except Exception as err:
424    print('\n'+75*'=')
425    print('Failed with import of GSASIIpath. This is unexpected.')
426    print('GSAS-II will not run without correcting this. Contact toby@anl.gov')
427    print(err)
428    print(75*'=')
429    sys.exit()
430
431if allBinaries and skipDownloadSteps:
432    print('Loading all binaries with command...')
433    if not GSASIIpath.svnSwitchDir('AllBinaries','',g2home+ 'Binaries/',None,True):
434        print('Binary load failed')
435        sys.exit()
436else:
437    GSASIIpath.DownloadG2Binaries(g2home)
438       
439#===========================================================================
440# test if the compiled files load correctly
441#===========================================================================
442
443script = """  # commands that test each module can at least be loaded & run something in pyspg
444try:
445    import GSASIIpath
446    GSASIIpath.SetBinaryPath(loadBinary=False)
447    import pyspg
448    import histogram2d
449    import polymask
450    import pypowder
451    import pytexture
452    pyspg.sgforpy('P -1')
453    print('==OK==')
454except Exception as err:
455    print(err)
456"""
457p = subprocess.Popen([sys.executable,'-c',script],stdout=subprocess.PIPE,stderr=subprocess.PIPE,
458                     cwd=path2GSAS2)
459res,err = p.communicate()
460if '==OK==' not in str(res) or p.returncode != 0:
461    print('\n'+75*'=')
462    print('Failed when testing the GSAS-II compiled files. GSAS-II will not run')
463    print('without correcting this.\n\nError message:')
464    if res: 
465        print(res.decode())
466    if err:
467        print(err.decode())
468    #print('\nAttempting to open a web page on compiling GSAS-II...')
469    print('Please see web page\nhttps://subversion.xray.aps.anl.gov/trac/pyGSAS/wiki/CompileGSASII')
470    #import webbrowser
471    #webbrowser.open_new('https://subversion.xray.aps.anl.gov/trac/pyGSAS/wiki/CompileGSASII')
472    print(75*'=')
473#    if '86' in platform.machine() and (sys.platform.startswith('linux')
474#                                        or sys.platform == "darwin"
475#                                        or sys.platform.startswith('win')):
476#        print('Platform '+sys.platform+' with processor type '+platform.machine()+' is supported')
477#    else:
478#        print('Platform '+sys.platform+' with processor type '+platform.machine()+' not is supported')
479    sys.exit()
480else:
481    print('Successfully tested compiled routines')
482#===========================================================================
483# import all .py files so that .pyc files get created
484if not skipInstallSteps:
485    print('Byte-compiling all .py files...')
486    import compileall
487    compileall.compile_dir(path2GSAS2,quiet=True)
488    print('done')
489#===========================================================================
490# platform-dependent stuff
491#===========================================================================
492if sys.version_info[0] > 2:
493    def execfile(file):
494        with open(file) as source_file:
495            exec(source_file.read())
496
497if skipInstallSteps:
498    pass
499#===========================================================================
500# on Windows, make a batch file with Python and GSAS-II location hard-coded
501elif sys.platform.startswith('win') and os.path.exists(
502    os.path.join(path2GSAS2,"makeBat.py")):
503    execfile(os.path.join(path2GSAS2,"makeBat.py"))
504#===========================================================================
505# on a Mac, make an applescript
506elif sys.platform.startswith('darwin') and os.path.exists(
507    os.path.join(path2GSAS2,"makeMacApp.py")):
508    sys.argv = [os.path.join(path2GSAS2,"makeMacApp.py")]
509    print(u'running '+sys.argv[0])
510    execfile(sys.argv[0])
511#===========================================================================
512# On linux, make desktop icon
513elif sys.platform.startswith('linux') and os.path.exists(
514    os.path.join(path2GSAS2,"makeLinux.py")):
515    sys.argv = [os.path.join(path2GSAS2,"makeLinux.py")]
516    print(u'running '+sys.argv[0])
517    execfile(sys.argv[0])
518
Note: See TracBrowser for help on using the repository browser.