source: trunk/GSASIIpath.py @ 3075

Last change on this file since 3075 was 3075, checked in by toby, 4 years ago

Allow editing of proxy info

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 30.9 KB
Line 
1# -*- coding: utf-8 -*-
2'''
3*GSASIIpath: locations & updates*
4---------------------------------
5
6Routines for dealing with file locations, etc.
7
8Determines the location of the compiled (.pyd or .so) libraries.
9
10Interfaces with subversion (svn):
11Determine the subversion release number by determining the highest version number
12where :func:`SetVersionNumber` is called (best done in every GSASII file).
13Other routines will update GSASII from the subversion server if svn can be
14found.
15
16Accesses configuration options, as defined in config.py
17'''
18
19import os
20import sys
21import platform
22import glob
23import subprocess
24import numpy as np
25
26g2home = 'https://subversion.xray.aps.anl.gov/pyGSAS'
27'Define the location of the GSAS-II subversion repository'
28   
29path2GSAS2 = os.path.dirname(os.path.realpath(__file__)) # location of this file; save before any changes in pwd
30
31# convert version numbers as '1.2.3' to integers (1002) and back (to 1.2)
32fmtver = lambda v: str(v//1000)+'.'+str(v%1000)
33intver = lambda vs: sum([int(i) for i in vs.split('.')[0:2]]*np.array((1000,1)))
34
35def GetConfigValue(key,default=None):
36    '''Return the configuration file value for key or a default value if not present
37   
38    :param str key: a value to be found in the configuration (config.py) file
39    :param default: a value to be supplied is none is in the config file or
40      the config file is not found. Defaults to None
41    :returns: the value found or the default.
42    '''
43    try:
44        return configDict.get(key,default)
45    except NameError: # this happens when building docs
46        return None
47
48def SetConfigValue(parmdict):
49    '''Set configuration variables from a dictionary where elements are lists
50    First item in list is the default value and second is the value to use.
51    '''
52    global configDict
53    for var in parmdict:
54        if var in configDict:
55            del configDict[var]
56        if isinstance(parmdict[var],tuple):
57            configDict[var] = parmdict[var]
58        else:
59            if parmdict[var][1] is None: continue
60            if parmdict[var][1] == '': continue
61            if parmdict[var][0] == parmdict[var][1]: continue
62            configDict[var] = parmdict[var][1]
63
64# routines for looking a version numbers in files
65version = -1
66def SetVersionNumber(RevString):
67    '''Set the subversion version number
68
69    :param str RevString: something like "$Revision: 3075 $"
70      that is set by subversion when the file is retrieved from subversion.
71
72    Place ``GSASIIpath.SetVersionNumber("$Revision: 3075 $")`` in every python
73    file.
74    '''
75    try:
76        RevVersion = int(RevString.split(':')[1].split()[0])
77        global version
78        version = max(version,RevVersion)
79    except:
80        pass
81       
82def GetVersionNumber():
83    '''Return the maximum version number seen in :func:`SetVersionNumber`
84    '''
85    if version > 1000:
86        return version
87    else:
88        return "unknown"
89
90def LoadConfigFile(filename):
91    '''Read a GSAS-II configuration file.
92    Comments (starting with "%") are removed, as are empty lines
93   
94    :param str filename: base file name (such as 'file.dat'). Files with this name
95      are located from the path and the contents of each are concatenated.
96    :returns: a list containing each non-empty (after removal of comments) line
97      found in every matching config file.
98    '''
99    info = []
100    for path in sys.path:
101        fil = os.path.join(path,filename)
102        if not os.path.exists(fil): continue
103        try:
104            i = 0
105            fp = open(fil,'r')
106            for line in fp:
107                expr = line.split('#')[0].strip()
108                if expr:
109                    info.append(expr)
110                    i += 1
111            print(str(i)+' lines read from config file '+fil)
112        finally:
113            fp.close()
114    return info
115
116
117# routines to interface with subversion
118proxycmds = []
119'Used to hold proxy information for subversion, set if needed in whichsvn'
120svnLocCache = None
121'Cached location of svn to avoid multiple searches for it'
122def getsvnProxy():
123    '''Loads a proxy for subversion from the file created by bootstrap.py
124    '''
125    proxyinfo = os.path.join(path2GSAS2,"proxyinfo.txt")
126    if os.path.exists(proxyinfo):
127        global proxycmds
128        proxycmds = []
129        fp = open(proxyinfo,'r')
130        host = fp.readline().strip()
131        port = fp.readline().strip()
132        fp.close()
133        setsvnProxy(host,port)
134        if not host.strip(): return '',''
135        return host,port
136
137def setsvnProxy(host,port):
138    '''Sets the svn commands needed to use a proxy
139    '''
140    global proxycmds
141    proxycmds = []
142    host = host.strip()
143    port = port.strip()
144    if not host.strip(): return
145    proxycmds.append('--config-option')
146    proxycmds.append('servers:global:http-proxy-host='+host)
147    proxycmds.append('--config-option')
148    proxycmds.append('servers:global:http-proxy-port='+port)
149       
150def whichsvn():
151    '''Returns a path to the subversion exe file, if any is found.
152    Searches the current path after adding likely places where GSAS-II
153    might install svn.
154
155    :returns: None if svn is not found or an absolute path to the subversion
156      executable file.
157    '''
158    # use a previosuly cached svn location
159    global svnLocCache
160    if svnLocCache: return svnLocCache
161    # prepare to find svn
162    is_exe = lambda fpath: os.path.isfile(fpath) and os.access(fpath, os.X_OK)
163    svnprog = 'svn'
164    if sys.platform.startswith('win'): svnprog += '.exe'
165    host,port = getsvnProxy()
166    if GetConfigValue('debug'):
167        print('Using proxy host {} port {}'.format(host,port))
168    # add likely places to find subversion when installed with GSAS-II
169    pathlist = os.environ["PATH"].split(os.pathsep)
170    pathlist.append(os.path.split(sys.executable)[0])
171    pathlist.append(path2GSAS2)
172    for rpt in ('..','bin'),('..','Library','bin'),('svn','bin'),('svn',),('.'):
173        pt = os.path.normpath(os.path.join(path2GSAS2,*rpt))
174        if os.path.exists(pt):
175            pathlist.insert(0,pt)   
176    # search path for svn or svn.exe
177    for path in pathlist:
178        exe_file = os.path.join(path, svnprog)
179        if is_exe(exe_file):
180            try:
181                p = subprocess.Popen([exe_file,'help'],stdout=subprocess.PIPE)
182                res = p.stdout.read()
183                p.communicate()
184                svnLocCache = os.path.abspath(exe_file)
185                return svnLocCache
186            except:
187                pass       
188    svnLocCache = None
189
190def svnVersion(svn=None):
191    '''Get the version number of the current subversion executable
192
193    :returns: a string with a version number such as "1.6.6" or None if
194      subversion is not found.
195
196    '''
197    if not svn: svn = whichsvn()
198    if not svn: return
199
200    cmd = [svn,'--version','--quiet']
201    s = subprocess.Popen(cmd,
202                         stdout=subprocess.PIPE,stderr=subprocess.PIPE)
203    out,err = s.communicate()
204    if err:
205        print 'subversion error!\nout=',out
206        print 'err=',err
207        return None
208    return out.strip()
209
210def svnVersionNumber(svn=None):
211    '''Get the version number of the current subversion executable
212
213    :returns: a fractional version number such as 1.6 or None if
214      subversion is not found.
215
216    '''
217    ver = svnVersion(svn)
218    if not ver: return 
219    M,m = ver.split('.')[:2]
220    return int(M)+int(m)/10.
221
222def svnGetLog(fpath=os.path.split(__file__)[0],version=None):
223    '''Get the revision log information for a specific version of the specified package
224
225    :param str fpath: path to repository dictionary, defaults to directory where
226       the current file is located.
227    :param int version: the version number to be looked up or None (default)
228       for the latest version.
229
230    :returns: a dictionary with keys (one hopes) 'author', 'date', 'msg', and 'revision'
231
232    '''
233    import xml.etree.ElementTree as ET
234    svn = whichsvn()
235    if not svn: return
236    if version is not None:
237        vstr = '-r'+str(version)
238    else:
239        vstr = '-rHEAD'
240
241    cmd = [svn,'log',fpath,'--xml',vstr]
242    if proxycmds: cmd += proxycmds
243    s = subprocess.Popen(cmd,
244                         stdout=subprocess.PIPE,stderr=subprocess.PIPE)
245    out,err = s.communicate()
246    if err:
247        print 'out=',out
248        print 'err=',err
249        return None
250    x = ET.fromstring(out)
251    d = {}
252    for i in x.iter('logentry'):
253        d = {'revision':i.attrib.get('revision','?')}
254        for j in i:
255            d[j.tag] = j.text
256        break # only need the first
257    return d
258
259svnLastError = ''
260def svnGetRev(fpath=os.path.split(__file__)[0],local=True):
261    '''Obtain the version number for the either the last update of the local version
262    or contacts the subversion server to get the latest update version (# of Head).
263
264    :param str fpath: path to repository dictionary, defaults to directory where
265       the current file is located
266    :param bool local: determines the type of version number, where
267       True (default): returns the latest installed update
268       False: returns the version number of Head on the server
269
270    :Returns: the version number as an str or
271       None if there is a subversion error (likely because the path is
272       not a repository or svn is not found). The error message is placed in
273       global variable svnLastError
274    '''
275
276    import xml.etree.ElementTree as ET
277    svn = whichsvn()
278    if not svn: return
279    if local:
280        cmd = [svn,'info',fpath,'--xml']
281    else:
282        cmd = [svn,'info',fpath,'--xml','-rHEAD']
283    if svnVersionNumber() >= 1.6:
284        cmd += ['--non-interactive', '--trust-server-cert']
285    if proxycmds: cmd += proxycmds
286    s = subprocess.Popen(cmd, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
287    out,err = s.communicate()
288    if err:
289        print 'svn failed\n',out
290        print 'err=',err
291        global svnLastError
292        svnLastError = err
293        return None
294    x = ET.fromstring(out)
295    for i in x.iter('entry'):
296        rev = i.attrib.get('revision')
297        if rev: return rev
298
299def svnFindLocalChanges(fpath=os.path.split(__file__)[0]):
300    '''Returns a list of files that were changed locally. If no files are changed,
301       the list has length 0
302
303    :param fpath: path to repository dictionary, defaults to directory where
304       the current file is located
305
306    :returns: None if there is a subversion error (likely because the path is
307       not a repository or svn is not found)
308
309    '''
310    import xml.etree.ElementTree as ET
311    svn = whichsvn()
312    if not svn: return
313    cmd = [svn,'status',fpath,'--xml']
314    if proxycmds: cmd += proxycmds
315    s = subprocess.Popen(cmd,
316                         stdout=subprocess.PIPE,stderr=subprocess.PIPE)
317    out,err = s.communicate()
318    if err: return None
319    x = ET.fromstring(out)
320    changed = []
321    for i in x.iter('entry'):
322        if i.find('wc-status').attrib.get('item') == 'modified': 
323            changed.append(i.attrib.get('path'))
324    return changed
325
326def svnUpdateDir(fpath=os.path.split(__file__)[0],version=None):
327    '''This performs an update of the files in a local directory from a server.
328
329    :param str fpath: path to repository dictionary, defaults to directory where
330       the current file is located
331    :param version: the number of the version to be loaded. Used only
332       cast as a string, but should be an integer or something that corresponds to a
333       string representation of an integer value when cast. A value of None (default)
334       causes the latest version on the server to be used.
335    '''
336    svn = whichsvn()
337    if not svn: return
338    if version:
339        verstr = '-r' + str(version)
340    else:
341        verstr = '-rHEAD'
342    cmd = [svn,'update',fpath,verstr,
343           '--non-interactive',
344           '--accept','theirs-conflict','--force']
345    if svnVersionNumber() >= 1.6:
346        cmd += ['--trust-server-cert']
347    if proxycmds: cmd += proxycmds
348    s = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
349    out,err = s.communicate()
350    if err:
351        print(60*"=")
352        print ("****** An error was noted, see below *********")
353        print(60*"=")
354        print err
355        sys.exit()
356
357def svnUpgrade(fpath=os.path.split(__file__)[0]):
358    '''This reformats subversion files, which may be needed if an upgrade of subversion is
359    done.
360
361    :param str fpath: path to repository dictionary, defaults to directory where
362       the current file is located
363    '''
364    svn = whichsvn()
365    if not svn: return
366    cmd = [svn,'upgrade',fpath,'--non-interactive']
367    if proxycmds: cmd += proxycmds
368    s = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
369    out,err = s.communicate()
370    if err:
371        print("svn upgrade did not happen (this is probably OK). Messages:")
372        print err
373           
374def svnUpdateProcess(version=None,projectfile=None,branch=None):
375    '''perform an update of GSAS-II in a separate python process'''
376    if not projectfile:
377        projectfile = ''
378    else:
379        projectfile = os.path.realpath(projectfile)
380        print 'restart using',projectfile
381    if branch:
382        version = branch
383    elif not version:
384        version = ''
385    else:
386        version = str(version)
387    # start the upgrade in a separate interpreter (avoids loading .pyd files)
388    subprocess.Popen([sys.executable,__file__,projectfile,version])
389    sys.exit()
390
391def svnSwitchDir(rpath,filename,baseURL,loadpath=None,verbose=True):
392    '''This performs a switch command to move files between subversion trees.
393    Note that if the files were previously downloaded,
394    the switch command will update the files to the newest version.
395   
396    :param str rpath: path to locate files, relative to the GSAS-II
397      installation path (defaults to path2GSAS2)
398    :param str URL: the repository URL
399    :param str loadpath: the prefix for the path, if specified. Defaults to path2GSAS2
400    :param bool verbose: if True (default) diagnostics are printed
401    '''
402    svn = whichsvn()
403    if not svn: return
404    URL = baseURL[:]
405    if baseURL[-1] != '/':
406        URL = baseURL + '/' + filename
407    else:
408        URL = baseURL + filename
409    if loadpath:
410        fpath = os.path.join(loadpath,rpath,filename)
411    else:
412        fpath = os.path.join(path2GSAS2,rpath,filename)
413    cmd = [svn,'switch',URL,fpath,
414           '--non-interactive','--trust-server-cert',
415           '--accept','theirs-conflict','--force']
416    if svnVersionNumber(svn) > 1.6: cmd += ['--ignore-ancestry']
417    if proxycmds: cmd += proxycmds
418    if verbose: print(u"Loading files to "+fpath+u"\n  from "+URL)
419    s = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
420    out,err = s.communicate()
421    if err:
422        print(60*"=")
423        print ("****** An error was noted, see below *********")
424        print(60*"=")
425        print 'out=',out
426        print 'err=',err
427        return False
428    if verbose:
429        print('=== Output from svn switch'+(43*'='))
430        print(out.strip())
431        print((70*'=')+'\n')
432    return True
433
434def svnInstallDir(URL,loadpath):
435    '''Load a subversion tree into a specified directory
436
437    :param str URL: the repository URL
438    :param str loadpath: path to locate files
439
440    '''
441    svn = whichsvn()
442    if not svn: return
443    cmd = [svn,'co',URL,loadpath,'--non-interactive']
444    if svnVersionNumber() >= 1.6: cmd += ['--trust-server-cert']
445    print("Loading files from "+URL)
446    if proxycmds: cmd += proxycmds
447    s = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
448    out,err = s.communicate()   #this fails too easily
449    if err:
450        print(60*"=")
451        print ("****** An error was noted, see below *********")
452        print(60*"=")
453        print err
454        return False
455    print ("Files installed at: "+loadpath)
456    return True
457
458def GetBinaryPrefix():
459    if sys.platform == "win32":
460        prefix = 'win'
461    elif sys.platform == "darwin":
462        prefix = 'mac'
463    elif sys.platform == "linux2":
464        prefix = 'linux'
465    else:
466        print(u'Unknown platform: '+sys.platform)
467        raise Exception('Unknown platform')
468    if platform.architecture()[0] == '64bit':
469        bits = '64'
470    else:
471        bits = '32'
472
473    # format current python version
474    pyver = 'p{}.{}'.format(*sys.version_info[0:2])
475
476    items = [prefix,bits,pyver]
477    return '_'.join(items)
478
479def DownloadG2Binaries(g2home,verbose=True):
480    '''Download GSAS-II binaries from appropriate section of the
481    GSAS-II svn repository based on the platform, numpy and Python
482    version
483    '''   
484    bindir = GetBinaryPrefix()
485    #npver = 'n{}.{}'.format(*np.__version__.split('.')[0:2])
486    inpver = intver(np.__version__)
487    svn = whichsvn()
488    if not svn:
489        print('**** unable to load files: svn not found ****')
490        return ''
491    # get binaries matching the required type -- other than for the numpy version
492    cmd = [svn, 'list', g2home + '/Binaries/','--non-interactive', '--trust-server-cert']
493    if proxycmds: cmd += proxycmds
494    if verbose:
495        print('Running svn command')
496        for item in cmd: print item,
497        print ""
498    p = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
499    res,err = p.communicate()
500    versions = {}
501    for d in res.split():
502        if d.startswith(bindir):
503            v = intver(d.rstrip('/').split('_')[3].lstrip('n'))
504            versions[v] = d
505    intVersionsList = sorted(versions.keys())
506    if not intVersionsList:
507        print('No binaries located')
508        return
509    elif inpver < min(intVersionsList):
510        vsel = min(intVersionsList)
511        print('Warning: The current numpy version, {}, is older than\n\tthe oldest dist version, {}'
512              .format(np.__version__,fmtver(vsel)))
513    elif inpver >= max(intVersionsList):
514        vsel = max(intVersionsList)
515        if verbose: print(
516                'FYI: The current numpy version, {}, is newer than the newest dist version {}'
517                .format(np.__version__,fmtver(vsel)))
518    else:
519        vsel = min(intVersionsList)
520        for v in intVersionsList:
521            if v <= inpver:
522                vsel = v
523            else:
524                if verbose: print(
525                        'FYI: Selecting dist version {} as the current numpy version, {},\n\tis older than the next dist version {}'
526                        .format(fmtver(vsel),np.__version__,fmtver(v)))
527                break
528    distdir = g2home + '/Binaries/' + versions[vsel]
529    # switch reset command: distdir = g2home + '/trunk/bindist'
530    svnSwitchDir('bindist','',distdir,verbose=verbose)
531    return os.path.join(path2GSAS2,'bindist')
532
533# def svnTestBranch(loc=None):
534#     '''Returns the name of the branch directory if the installation has been switched.
535#     Returns none, if not a branch
536#     the test 2frame branch. False otherwise
537#     '''
538#     if loc is None: loc = path2GSAS2
539#     svn = whichsvn()
540#     if not svn:
541#         print('**** unable to load files: svn not found ****')
542#         return ''
543#     cmd = [svn, 'info', loc]
544#     if proxycmds: cmd += proxycmds
545#     p = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
546#     res,err = p.communicate()
547#     for l in res.split('\n'):
548#         if "Relative URL:" in l: break
549#     if "/branch/" in l:
550#         return l[l.find("/branch/")+8:].strip()
551#     else:
552#         return None
553   
554def svnSwitch2branch(branch=None,loc=None,svnHome=None):
555    '''Switch to a subversion branch if specified. Switches to trunk otherwise.
556    '''
557    if svnHome is None: svnHome = g2home
558    svnURL = svnHome + '/trunk'
559    if branch:
560        if svnHome.endswith('/'):
561            svnURL = svnHome[:-1]
562        else:
563            svnURL = svnHome
564        if branch.startswith('/'):
565            svnURL += branch
566        else:
567            svnURL += '/' + branch
568    svnSwitchDir('','',svnURL,loadpath=loc)
569   
570
571def IPyBreak_base(userMsg=None):
572    '''A routine that invokes an IPython session at the calling location
573    This routine is only used when debug=True is set in config.py
574    '''
575    savehook = sys.excepthook # save the exception hook
576    try: 
577        from IPython.terminal.embed import InteractiveShellEmbed
578    except ImportError:
579        try:
580            # try the IPython 0.12 approach
581            from IPython.frontend.terminal.embed import InteractiveShellEmbed
582        except ImportError:
583            print 'IPython InteractiveShellEmbed not found'
584            return
585    import inspect
586    ipshell = InteractiveShellEmbed()
587
588    frame = inspect.currentframe().f_back
589    msg   = 'Entering IPython console inside {0.f_code.co_filename} at line {0.f_lineno}\n'.format(frame)
590    if userMsg: msg += userMsg
591    ipshell(msg,stack_depth=2) # Go up one level, to see the calling routine
592    sys.excepthook = savehook # reset IPython's change to the exception hook
593
594def exceptHook(*args):
595    '''A routine to be called when an exception occurs. It prints the traceback
596    with fancy formatting and then calls an IPython shell with the environment
597    of the exception location.
598   
599    This routine is only used when debug=True is set in config.py   
600    '''
601    from IPython.core import ultratb
602    if 'win' in sys.platform:
603        ultratb.FormattedTB(call_pdb=False,color_scheme='NoColor')(*args)
604    else:
605        ultratb.FormattedTB(call_pdb=False,color_scheme='LightBG')(*args)
606    try: 
607        from IPython.terminal.embed import InteractiveShellEmbed
608    except ImportError:
609        try:
610            # try the IPython 0.12 approach
611            from IPython.frontend.terminal.embed import InteractiveShellEmbed
612        except ImportError:
613            print 'IPython InteractiveShellEmbed not found'
614            return
615    import inspect
616    frame = inspect.getinnerframes(args[2])[-1][0]
617    msg   = 'Entering IPython console at {0.f_code.co_filename} at line {0.f_lineno}\n'.format(frame)
618    savehook = sys.excepthook # save the exception hook
619    try:
620        InteractiveShellEmbed(banner1=msg)(local_ns=frame.f_locals,global_ns=frame.f_globals)
621    except: # use a different call for IPython 5
622        class c(object): pass
623        pseudomod = c() # create something that acts like a module
624        pseudomod.__dict__ = frame.f_locals
625        InteractiveShellEmbed(banner1=msg)(module=pseudomod,global_ns=frame.f_globals)
626    sys.excepthook = savehook # reset IPython's change to the exception hook
627
628def DoNothing():
629    '''A routine that does nothing. This is called in place of IPyBreak and pdbBreak
630    except when the debug option is set True in config.py
631    '''
632    pass 
633
634IPyBreak = DoNothing
635pdbBreak = DoNothing
636def InvokeDebugOpts():
637    'Called in GSASII.py to set up debug options'
638    if GetConfigValue('debug'):
639        print 'Debug on: IPython: Exceptions and G2path.IPyBreak(); pdb: G2path.pdbBreak()'
640        sys.excepthook = exceptHook
641        import pdb
642        global pdbBreak
643        pdbBreak = pdb.set_trace
644        global IPyBreak
645        IPyBreak = IPyBreak_base
646
647def TestSPG(fpth):
648    '''Test if pyspg.[so,.pyd] can be run from a location in the path
649    '''
650    if not os.path.exists(fpth): return False
651    if not glob.glob(os.path.join(fpth,'pyspg.*')): return False
652    savpath = sys.path[:]
653    sys.path = [fpth]
654    # test to see if a shared library can be used
655    try:
656        import pyspg
657        pyspg.sgforpy('P -1')
658    except Exception as err:
659        print(70*'=')
660        print('Failed to run pyspg in {}\nerror: {}'.format(fpth,err))
661        print(70*'=')
662        sys.path = savpath
663        return False
664    sys.path = savpath
665    return True
666   
667# see if a directory for local modifications is defined. If so, stick that in the path
668if os.path.exists(os.path.expanduser('~/.G2local/')):
669    sys.path.insert(0,os.path.expanduser('~/.G2local/'))
670    import glob
671    fl = glob.glob(os.path.expanduser('~/.G2local/GSASII*.py*'))
672    files = ""
673    prev = None
674    for f in sorted(fl): # make a list of files, dropping .pyc files where a .py exists
675        f = os.path.split(f)[1]
676        if os.path.splitext(f)[0] == prev: continue
677        prev = os.path.splitext(f)[0]
678        if files: files += ", "
679        files += f
680    if files:
681        print("*"*75)
682        print("Warning: the following source files are locally overridden in "+os.path.expanduser('~/.G2local/'))
683        print("  "+files)
684        print("*"*75)
685
686BinaryPathLoaded = False
687def SetBinaryPath(printInfo=True):
688    '''
689    Add location of GSAS-II shared libraries (binaries: .so or .pyd files) to path
690   
691    This routine must be executed after GSASIIpath is imported and before any other
692    GSAS-II imports are done.
693    '''
694    # do this only once no matter how many times it is called
695    global BinaryPathLoaded
696    if BinaryPathLoaded: return
697    try:
698        inpver = intver(np.__version__)
699    except AttributeError: # happens on building docs
700        return
701    binpath = None
702    binprfx = GetBinaryPrefix()
703    for loc in os.path.abspath(sys.path[0]),os.path.abspath(os.path.split(__file__)[0]):
704        # Look at bin directory (created by a local compile) before looking for standard dist files
705        searchpathlist = [os.path.join(loc,'bin')]
706        # also look for matching binary dist in loc/AllBinaries
707        versions = {}
708        for d in glob.glob(os.path.join(loc,'AllBinaries',binprfx+'*')):
709            v = intver(d.rstrip('/').split('_')[3].lstrip('n'))
710            versions[v] = d
711        searchpathlist = [os.path.join(loc,'bin')]
712        vmin = None
713        vmax = None
714        for v in sorted(versions.keys()):
715            if v <= inpver:
716                vmin = v
717            elif v > inpver:
718                vmax = v
719                break
720        if vmin in versions:
721            searchpathlist.append(versions[vmin])
722        if vmax in versions:
723            searchpathlist.append(versions[vmax])
724        searchpathlist.append(os.path.join(loc,'bindist'))
725        for fpth in searchpathlist:
726            if TestSPG(fpth):
727                binpath = fpth
728                break       
729        if binpath: break
730    if binpath:                                            # were GSAS-II binaries found
731        sys.path.insert(0,binpath)
732        if printInfo:
733            print('GSAS-II binary directory: {}'.format(binpath))
734        BinaryPathLoaded = True
735    else:                                                  # try loading them
736        if printInfo:
737            print('Attempting to download GSAS-II binary files...')
738        try:
739            binpath = DownloadG2Binaries(g2home)
740        except AttributeError:   # this happens when building in Read The Docs
741            if printInfo:
742                print('Problem with download')
743        if binpath and TestSPG(binpath):
744            if printInfo:
745                print('GSAS-II binary directory: {}'.format(binpath))
746            sys.path.insert(0,binpath)
747            BinaryPathLoaded = True
748        # this must be imported before anything that imports any .pyd/.so file for GSASII
749        else:
750            #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
751            #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
752            # patch: use old location based on the host OS and the python version, 
753            # path is relative to location of the script that is called as well as this file
754            BinaryPathLoaded = True
755            bindir = None
756            if sys.platform == "win32":
757                if platform.architecture()[0] == '64bit':
758                    bindir = 'binwin64-%d.%d' % sys.version_info[0:2]
759                else:
760                    bindir = 'binwin%d.%d' % sys.version_info[0:2]
761            elif sys.platform == "darwin":
762                if platform.architecture()[0] == '64bit':
763                    bindir = 'binmac64-%d.%d' % sys.version_info[0:2]
764                else:
765                    bindir = 'binmac%d.%d' % sys.version_info[0:2]
766                #if platform.mac_ver()[0].startswith('10.5.'):
767                #    bindir += '_10.5'
768            elif sys.platform == "linux2":
769                if platform.architecture()[0] == '64bit':
770                    bindir = 'binlinux64-%d.%d' % sys.version_info[0:2]
771                else:
772                    bindir = 'binlinux%d.%d' % sys.version_info[0:2]
773            for loc in os.path.abspath(sys.path[0]),os.path.abspath(os.path.split(__file__)[0]):
774            # Look at bin directory (created by a local compile) before standard dist
775            # that at the top of the path
776                fpth = os.path.join(loc,bindir)
777                binpath = fpth
778                if TestSPG(fpth):
779                    sys.path.insert(0,binpath)
780                    if printInfo:
781                        print('\n'+75*'*')
782                        print('  Warning. Using an old-style GSAS-II binary library. This is unexpected')
783                        print('  and will break in future GSAS-II versions. Please contact toby@anl.gov')
784                        print('  so we can learn what is not working on your installation.')
785                        print('GSAS-II binary directory: {}'.format(binpath))
786                        print(75*'*')
787                    break
788            else:
789            # end patch
790            #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
791            #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
792                if printInfo:
793                    print(75*'*')
794                    print('Use of GSAS-II binary directory {} failed!'.format(binpath))
795                    print(75*'*')
796                raise Exception,"**** ERROR GSAS-II binary libraries not found, GSAS-II cannot run ****"
797
798    # add the data import and export directory to the search path
799    newpath = os.path.join(path2GSAS2,'imports')
800    if newpath not in sys.path: sys.path.append(newpath)
801    newpath = os.path.join(path2GSAS2,'exports')
802    if newpath not in sys.path: sys.path.append(newpath)
803
804    # setup read of config.py, if present
805    global configDict
806    try:
807        import config
808        configDict = config.__dict__
809        import inspect
810        vals = [True for i in inspect.getmembers(config) if '__' not in i[0]]
811        if printInfo:
812            print str(len(vals))+' values read from config file '+os.path.abspath(config.__file__)
813    except ImportError:
814        configDict = {'Clip_on':True}
815    except Exception as err:
816        if printInfo:
817            print("Error importing config.py file: "+str(err))
818        configDict = {'Clip_on':True}
819
820if __name__ == '__main__':
821    '''What follows is called to update (or downdate) GSAS-II in a separate process.
822    '''
823    import time
824    time.sleep(1) # delay to give the main process a chance to exit
825    # perform an update and restart GSAS-II
826    project,version = sys.argv[1:3]
827    loc = os.path.dirname(__file__)
828    if version == 'trunk':
829        svnSwitch2branch('')
830    elif '/' in version:
831        svnSwitch2branch(version)
832    elif version:
833        print("Regress to version "+str(version))
834        svnUpdateDir(loc,version=version)
835    else:
836        print("Update to current version")
837        svnUpdateDir(loc)
838    ex = sys.executable
839    if sys.platform == "darwin": # mac requires pythonw which is not always reported as sys.executable
840        if os.path.exists(ex+'w'): ex += 'w'
841    if project:
842        print("Restart GSAS-II with project file "+str(project))
843        subprocess.Popen([ex,os.path.join(loc,'GSASII.py'),project])
844    else:
845        print("Restart GSAS-II without a project file ")
846        subprocess.Popen([ex,os.path.join(loc,'GSASII.py')])
847    print 'exiting update process'
848    sys.exit()
Note: See TracBrowser for help on using the repository browser.