source: trunk/GSASIIpath.py @ 981

Last change on this file since 981 was 981, checked in by toby, 10 years ago

introduce regress option; fix esd printing; more docs; new Mac app with drag & drop for open; control reset of ref list on load

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 8.2 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    bindir = 'binmac%d.%d' % sys.version_info[0:2]
31    import platform
32    if platform.mac_ver()[0].startswith('10.5.'):
33        bindir += '_10.5'
34elif sys.platform == "linux2":
35    if platform.architecture()[0] == '64bit':
36        bindir = 'binlinux64-%d.%d' % sys.version_info[0:2]
37    else:
38        bindir = 'binlinux%d.%d' % sys.version_info[0:2]
39for loc in sys.path[0],os.path.split(__file__)[0]:
40    if bindir:
41        if os.path.exists(os.path.join(loc,bindir)) and os.path.join(loc,bindir) not in sys.path: 
42            sys.path.insert(0,os.path.join(loc,bindir))
43        # is there a bin directory? (created by a local compile), if so put
44        # that at the top of the path
45    if os.path.exists(os.path.join(loc,'bin')) and os.path.getsize(os.path.join(loc,'bin')):
46        bindir = 'bin'
47        if os.path.join(loc,'bin') not in sys.path: 
48            sys.path.insert(0,os.path.join(loc,bindir))
49print 'GSAS-II binary directory: ',os.path.join(loc,bindir)
50if bindir == None:
51    raise Exception,"**** ERROR GSAS-II binary libraries not found, GSAS-II fails ****"
52
53# routines for looking a version numbers in files
54version = -1
55def SetVersionNumber(RevString):
56    '''Set the subversion version number
57
58    :param str RevString: something like "$Revision: 981 $"
59      that is set by subversion when the file is retrieved from subversion.
60
61    Place ``GSASIIpath.SetVersionNumber("$Revision: 981 $")`` in every python
62    file.
63    '''
64    try:
65        RevVersion = int(RevString.split(':')[1].split()[0])
66        global version
67        version = max(version,RevVersion)
68    except:
69        pass
70       
71def GetVersionNumber():
72    '''Return the maximum version number seen in :func:`SetVersionNumber`
73    '''
74    return version
75
76# routines to interface with subversion
77def whichsvn():
78    '''Returns a path to the subversion exe file, if any is found.
79    Searches the current path as well as subdirectory "svn" and
80    "svn/bin" in the location of the GSASII source files.
81
82    :returns: None if svn is not found or an absolute path to the subversion
83    executable file .
84    '''
85    def is_exe(fpath):
86        return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
87    svnprog = 'svn'
88    if sys.platform == "win32": svnprog += '.exe'
89    pathlist = os.environ["PATH"].split(os.pathsep)
90    pathlist.insert(0,os.path.join(os.path.split(__file__)[0],'svn'))
91    pathlist.insert(1,os.path.join(os.path.split(__file__)[0],'svn','bin'))
92    for path in pathlist:
93        exe_file = os.path.join(path, svnprog)
94        if is_exe(exe_file):
95            return os.path.abspath(exe_file)
96
97def svnGetLog(fpath=os.path.split(__file__)[0],version=None):
98    '''Get the revision log information for a specific version of the
99
100    :param str fpath: path to repository dictionary, defaults to directory where
101       the current file is located.
102    :param int version: the version number to be looked up or None (default)
103       for the latest version.
104
105    :returns: a dictionary with keys (one hopes) 'author', 'date', 'msg', and 'revision'
106
107    '''
108    import subprocess
109    import xml.etree.ElementTree as ET
110    svn = whichsvn()
111    if not svn: return
112    if version is not None:
113        vstr = '-r'+str(version)
114    else:
115        vstr = '-rHEAD'
116
117    cmd = [svn,'log',fpath,'--xml',vstr]
118    s = subprocess.Popen(cmd,
119                         stdout=subprocess.PIPE,stderr=subprocess.PIPE)
120    out,err = s.communicate()
121    if err:
122        print 'out=',out
123        print 'err=',err
124        return None
125    x = ET.fromstring(out)
126    d = {}
127    for i in x.iter('logentry'):
128        d = {'revision':i.attrib.get('revision','?')}
129        for j in i:
130            d[j.tag] = j.text
131        break # only need the first
132    return d
133
134def svnGetRev(fpath=os.path.split(__file__)[0],local=True):
135    '''Obtain the version number for the either the last update of the local version
136    or contacts the subversion server to get the latest update version (# of Head).
137
138    :param str fpath: path to repository dictionary, defaults to directory where
139       the current file is located
140    :param bool local: determines the type of version number, where
141       True (default): returns the latest installed update
142       False: returns the version number of Head on the server
143
144    :Returns: the version number as an str or
145       None if there is a subversion error (likely because the path is
146       not a repository or svn is not found)
147    '''
148
149    import subprocess
150    import xml.etree.ElementTree as ET
151    svn = whichsvn()
152    if not svn: return
153    if local:
154        cmd = [svn,'info',fpath,'--xml']
155    else:
156        cmd = [svn,'info',fpath,'--xml','-rHEAD']
157    s = subprocess.Popen(cmd,
158                         stdout=subprocess.PIPE,stderr=subprocess.PIPE)
159    out,err = s.communicate()
160    if err:
161        print 'out=',out
162        print 'err=',err
163        return None
164    x = ET.fromstring(out)
165    for i in x.iter('entry'):
166        rev = i.attrib.get('revision')
167        if rev: return rev
168
169def svnFindLocalChanges(fpath=os.path.split(__file__)[0]):
170    '''Returns a list of files that were changed locally. If no files are changed,
171       the list has length 0
172
173    :param fpath: path to repository dictionary, defaults to directory where
174       the current file is located
175
176    :returns: None if there is a subversion error (likely because the path is
177       not a repository or svn is not found)
178
179    '''
180    import subprocess
181    import xml.etree.ElementTree as ET
182    svn = whichsvn()
183    if not svn: return
184    s = subprocess.Popen([svn,'status',fpath,'--xml'],
185                         stdout=subprocess.PIPE,stderr=subprocess.PIPE)
186    out,err = s.communicate()
187    if err: return None
188    x = ET.fromstring(out)
189    changed = []
190    for i in x.iter('entry'):
191        if i.find('wc-status').attrib.get('item') == 'modified': 
192            changed.append(i.attrib.get('path'))
193    return changed
194
195def svnUpdateDir(fpath=os.path.split(__file__)[0],version=None):
196    '''This performs an update of the files in a local directory from a server.
197
198    :param fpath: path to repository dictionary, defaults to directory where
199       the current file is located
200
201    :returns: A dictionary with the files that have been changed/added and
202          a code describing how they have been updated (see changetype) ro
203          None if there is a subversion error (likely because the path is
204          not a repository or svn is not found)
205
206    '''
207    import subprocess
208    changetype = {'A': 'Added', 'D': 'Deleted', 'U': 'Updated',
209                  'C': 'Conflict', 'G': 'Merged', 'E': 'Replaced'}
210    svn = whichsvn()
211    if not svn: return
212    if version:
213        verstr = '-r' + str(version)
214    else:
215        verstr = '-rHEAD'
216    cmd = [svn,'update',fpath,verstr,
217           '--non-interactive',
218           '--accept','theirs-conflict','--force']
219    s = subprocess.Popen(cmd, 
220                         stdout=subprocess.PIPE,stderr=subprocess.PIPE)
221    out,err = s.communicate()
222    print out
223    if err:
224        print err
225        return
226    l = out.split()
227    updates = {}
228    for i,j in zip(l[::2],l[1::2]):
229        if i == 'Updated': break
230        if i == 'At': break
231        t = changetype.get(i[0])
232        if not t: continue
233        f = os.path.split(j)[1]
234        if updates.get(t):
235            updates[t] += ', '+f
236        else:
237            updates[t] = f
238    return updates
Note: See TracBrowser for help on using the repository browser.