source: branch/2frame/GSASIIpath.py @ 2952

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

GSASII installation: support downloading of all binaries

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