source: trunk/GSASIIpath.py @ 1513

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

update and rebuild docs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 11.3 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'''
16
17import os
18import sys
19import platform
20# determine a binary path for the pyd files based on the host OS and the python version, 
21# path is relative to location of the script that is called as well as this file
22# this must be imported before anything that imports any .pyd/.so file for GSASII
23bindir = None
24if sys.platform == "win32":
25    if platform.architecture()[0] == '64bit':
26        bindir = 'binwin64-%d.%d' % sys.version_info[0:2]
27    else:
28        bindir = 'binwin%d.%d' % sys.version_info[0:2]
29elif sys.platform == "darwin":
30    import platform
31    if platform.architecture()[0] == '64bit':
32        bindir = 'binmac64-%d.%d' % sys.version_info[0:2]
33    else:
34        bindir = 'binmac%d.%d' % sys.version_info[0:2]
35    if platform.mac_ver()[0].startswith('10.5.'):
36        bindir += '_10.5'
37elif sys.platform == "linux2":
38    if platform.architecture()[0] == '64bit':
39        bindir = 'binlinux64-%d.%d' % sys.version_info[0:2]
40    else:
41        bindir = 'binlinux%d.%d' % sys.version_info[0:2]
42for loc in sys.path[0],os.path.abspath(os.path.split(__file__)[0]):
43    if bindir:
44        if os.path.exists(os.path.join(loc,bindir)) and os.path.join(loc,bindir) not in sys.path: 
45            sys.path.insert(0,os.path.join(loc,bindir))
46        # is there a bin directory? (created by a local compile), if so put
47        # that at the top of the path
48    if os.path.exists(os.path.join(loc,'bin')) and os.path.getsize(os.path.join(loc,'bin')):
49        bindir = 'bin'
50        if os.path.join(loc,'bin') not in sys.path: 
51            sys.path.insert(0,os.path.join(loc,bindir))
52print 'GSAS-II binary directory: ',os.path.join(loc,bindir)
53if bindir == None:
54    raise Exception,"**** ERROR GSAS-II binary libraries not found, GSAS-II fails ****"
55# add the data import and export directory to the search path
56path2GSAS2 = os.path.dirname(os.path.realpath(__file__)) # location of this file; save before any changes in pwd
57newpath = os.path.join(path2GSAS2,'imports')
58if newpath not in sys.path: sys.path.append(newpath)
59newpath = os.path.join(path2GSAS2,'exports')
60if newpath not in sys.path: sys.path.append(newpath)
61
62# setup read of config.py, if present
63try:
64    import config
65    configDict = config.__dict__
66    import inspect
67    vals = [True for i in inspect.getmembers(config) if '__' not in i[0]]
68    print str(len(vals))+' values read from config file '+os.path.abspath(config.__file__)
69except ImportError:
70    configDict = {}
71   
72def GetConfigValue(key,default=None):
73    '''Return the configuration file value for key or a default value if not present
74   
75    :param str key: a value to be found in the configuration (config.py) file
76    :param default: a value to be supplied is none is in the config file or
77      the config file is not found. Defaults to None
78    :returns: the value found or the default.
79    '''
80    return configDict.get(key,default)
81
82# routines for looking a version numbers in files
83version = -1
84def SetVersionNumber(RevString):
85    '''Set the subversion version number
86
87    :param str RevString: something like "$Revision: 1513 $"
88      that is set by subversion when the file is retrieved from subversion.
89
90    Place ``GSASIIpath.SetVersionNumber("$Revision: 1513 $")`` in every python
91    file.
92    '''
93    try:
94        RevVersion = int(RevString.split(':')[1].split()[0])
95        global version
96        version = max(version,RevVersion)
97    except:
98        pass
99       
100def GetVersionNumber():
101    '''Return the maximum version number seen in :func:`SetVersionNumber`
102    '''
103    return version
104
105def LoadConfigFile(filename):
106    '''Read a GSAS-II configuration file.
107    Comments (starting with "%") are removed, as are empty lines
108   
109    :param str filename: base file name (such as 'file.dat'). Files with this name
110      are located from the path and the contents of each are concatenated.
111    :returns: a list containing each non-empty (after removal of comments) line
112      found in every matching config file.
113    '''
114    info = []
115    for path in sys.path:
116        fil = os.path.join(path,filename)
117        if not os.path.exists(fil): continue
118        try:
119            i = 0
120            fp = open(fil,'r')
121            for line in fp:
122                expr = line.split('#')[0].strip()
123                if expr:
124                    info.append(expr)
125                    i += 1
126            print(str(i)+' lines read from config file '+fil)
127        finally:
128            fp.close()
129    return info
130
131
132# routines to interface with subversion
133def whichsvn():
134    '''Returns a path to the subversion exe file, if any is found.
135    Searches the current path as well as subdirectory "svn" and
136    "svn/bin" in the location of the GSASII source files.
137
138    :returns: None if svn is not found or an absolute path to the subversion
139      executable file.
140    '''
141    def is_exe(fpath):
142        return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
143    svnprog = 'svn'
144    if sys.platform == "win32": svnprog += '.exe'
145    pathlist = os.environ["PATH"].split(os.pathsep)
146    pathlist.insert(0,os.path.join(os.path.split(__file__)[0],'svn'))
147    pathlist.insert(1,os.path.join(os.path.split(__file__)[0],'svn','bin'))
148    for path in pathlist:
149        exe_file = os.path.join(path, svnprog)
150        if is_exe(exe_file):
151            return os.path.abspath(exe_file)
152
153def svnGetLog(fpath=os.path.split(__file__)[0],version=None):
154    '''Get the revision log information for a specific version of the
155
156    :param str fpath: path to repository dictionary, defaults to directory where
157       the current file is located.
158    :param int version: the version number to be looked up or None (default)
159       for the latest version.
160
161    :returns: a dictionary with keys (one hopes) 'author', 'date', 'msg', and 'revision'
162
163    '''
164    import subprocess
165    import xml.etree.ElementTree as ET
166    svn = whichsvn()
167    if not svn: return
168    if version is not None:
169        vstr = '-r'+str(version)
170    else:
171        vstr = '-rHEAD'
172
173    cmd = [svn,'log',fpath,'--xml',vstr]
174    s = subprocess.Popen(cmd,
175                         stdout=subprocess.PIPE,stderr=subprocess.PIPE)
176    out,err = s.communicate()
177    if err:
178        print 'out=',out
179        print 'err=',err
180        return None
181    x = ET.fromstring(out)
182    d = {}
183    for i in x.iter('logentry'):
184        d = {'revision':i.attrib.get('revision','?')}
185        for j in i:
186            d[j.tag] = j.text
187        break # only need the first
188    return d
189
190def svnGetRev(fpath=os.path.split(__file__)[0],local=True):
191    '''Obtain the version number for the either the last update of the local version
192    or contacts the subversion server to get the latest update version (# of Head).
193
194    :param str fpath: path to repository dictionary, defaults to directory where
195       the current file is located
196    :param bool local: determines the type of version number, where
197       True (default): returns the latest installed update
198       False: returns the version number of Head on the server
199
200    :Returns: the version number as an str or
201       None if there is a subversion error (likely because the path is
202       not a repository or svn is not found)
203    '''
204
205    import subprocess
206    import xml.etree.ElementTree as ET
207    svn = whichsvn()
208    if not svn: return
209    if local:
210        cmd = [svn,'info',fpath,'--xml']
211    else:
212        cmd = [svn,'info',fpath,'--xml','-rHEAD']
213    s = subprocess.Popen(cmd,
214                         stdout=subprocess.PIPE,stderr=subprocess.PIPE)
215    out,err = s.communicate()
216    if err:
217        print 'out=',out
218        print 'err=',err
219        return None
220    x = ET.fromstring(out)
221    for i in x.iter('entry'):
222        rev = i.attrib.get('revision')
223        if rev: return rev
224
225def svnFindLocalChanges(fpath=os.path.split(__file__)[0]):
226    '''Returns a list of files that were changed locally. If no files are changed,
227       the list has length 0
228
229    :param fpath: path to repository dictionary, defaults to directory where
230       the current file is located
231
232    :returns: None if there is a subversion error (likely because the path is
233       not a repository or svn is not found)
234
235    '''
236    import subprocess
237    import xml.etree.ElementTree as ET
238    svn = whichsvn()
239    if not svn: return
240    s = subprocess.Popen([svn,'status',fpath,'--xml'],
241                         stdout=subprocess.PIPE,stderr=subprocess.PIPE)
242    out,err = s.communicate()
243    if err: return None
244    x = ET.fromstring(out)
245    changed = []
246    for i in x.iter('entry'):
247        if i.find('wc-status').attrib.get('item') == 'modified': 
248            changed.append(i.attrib.get('path'))
249    return changed
250
251def svnUpdateDir(fpath=os.path.split(__file__)[0],version=None):
252    '''This performs an update of the files in a local directory from a server.
253
254    :param str fpath: path to repository dictionary, defaults to directory where
255       the current file is located
256    :param version: the number of the version to be loaded. Used only
257       cast as a string, but should be an integer or something that corresponds to a
258       string representation of an integer value when cast. A value of None (default)
259       causes the latest version on the server to be used.
260    '''
261    import subprocess
262    svn = whichsvn()
263    if not svn: return
264    if version:
265        verstr = '-r' + str(version)
266    else:
267        verstr = '-rHEAD'
268    cmd = [svn,'update',fpath,verstr,
269           '--non-interactive',
270           '--accept','theirs-conflict','--force']
271    s = subprocess.Popen(cmd, 
272                         stdout=subprocess.PIPE,stderr=subprocess.PIPE)
273    out,err = s.communicate()
274    print out
275    if err:
276        print(60*"=")
277        print ("****** An error was noted, see below *********")
278        print(60*"=")
279        print err
280        sys.exit()
281
282def svnUpdateProcess(version=None,projectfile=None):
283    '''perform an update of GSAS-II in a separate python process'''
284    import subprocess
285    if not projectfile:
286        projectfile = ''
287    else:
288        projectfile = os.path.realpath(projectfile)
289        print 'restart using',projectfile
290    if not version:
291        version = ''
292    else:
293        version = str(version)
294    # start the upgrade in a separate interpreter (avoids loading .pyd files)
295    subprocess.Popen([sys.executable,__file__,projectfile,version])
296    sys.exit()
297
298if __name__ == '__main__':
299    import subprocess
300    import time
301    time.sleep(1) # delay to give the main process a chance to exit
302    # perform an update and restart GSAS-II
303    project,version = sys.argv[1:3]
304    loc = os.path.dirname(__file__)
305    if version:
306        print("Regress to version "+str(version))
307        svnUpdateDir(loc,version=version)
308    else:
309        print("Update to current version")
310        svnUpdateDir(loc)
311    if project:
312        print("Restart GSAS-II with project file "+str(project))
313        subprocess.Popen([sys.executable,os.path.join(loc,'GSASII.py'),project])
314    else:
315        print("Restart GSAS-II without a project file ")
316        subprocess.Popen([sys.executable,os.path.join(loc,'GSASII.py')])
317    print 'exiting update process'
318    sys.exit()
319   
Note: See TracBrowser for help on using the repository browser.