source: branch/logging/GSASIIpath.py @ 1511

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

add config file support

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