source: install/bootstrap.py @ 3787

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

fix bootstrap properties

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