source: trunk/GSASIIpath.py @ 1453

Last change on this file since 1453 was 1413, checked in by toby, 11 years ago

Add config support; default expressions

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