source: trunk/GSASIIpath.py @ 3088

Last change on this file since 3088 was 3077, checked in by toby, 8 years ago

fix bug on svn check

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