Package topo :: Package misc :: Module filepath
[hide private]
[frames] | no frames]

Source Code for Module topo.misc.filepath

  1  """ 
  2  Functions and classes to simplify dealing with paths. 
  3   
  4  For portable code: 
  5    - specify paths in unix (rather than Windows) style; 
  6    - use resolve_path() for paths to existing files to be read,  
  7      and normalize_path() for paths to new files to be written. 
  8   
  9  The location in which new files are created by default can be 
 10  controlled by the output_path module attribute, which applies 
 11  whenever a particular location is not specified explicitly. 
 12   
 13  $Id: filepath.py 10672 2009-10-28 01:00:50Z ceball $ 
 14  """ 
 15  __version__='$Revision: 10672 $' 
 16   
 17  import os.path 
 18  import sys 
 19   
 20  import param 
 21   
 22   
 23  # copied from scipy/weave/catalog.py (scipy svn 5552) 
 24  import socket,tempfile 
25 -def is_writable(dir):
26 """Determine whether a given directory is writable in a portable manner. 27 28 :Parameters: 29 - dir: string 30 A string represeting a path to a directory on the filesystem. 31 32 :Returns: 33 True or False. 34 """ 35 36 # Do NOT use a hardcoded name here due to the danger from race conditions 37 # on NFS when multiple processes are accessing the same base directory in 38 # parallel. We use both hostname and pocess id for the prefix in an 39 # attempt to ensure that there can really be no name collisions (tempfile 40 # appends 6 random chars to this prefix). 41 prefix = 'dummy_%s_%s_' % (socket.gethostname(),os.getpid()) 42 try: 43 tmp = tempfile.TemporaryFile(prefix=prefix,dir=dir) 44 except OSError: 45 return False 46 # The underlying file is destroyed upon closing the file object (under 47 # *nix, it was unlinked at creation time) 48 tmp.close() 49 return True
50 51
52 -class Filename(param.Parameter):
53 """ 54 Filename is a Parameter that can be set to a string specifying the 55 path of a file (in unix style), and returns it in the format of 56 the user's operating system. Additionally, the specified path can 57 be absolute or relative to: 58 59 * any of the paths specified in the search_paths attribute; 60 61 * any of the paths searched by resolve_path() (see doc for that 62 function). 63 """ 64 __slots__ = ['search_paths'] 65
66 - def __init__(self,default=None,search_paths=[],**params):
67 self.search_paths = search_paths 68 super(Filename,self).__init__(default,**params)
69 70
71 - def __set__(self,obj,val):
72 """ 73 Call Parameter's __set__, but warn if the file cannot be found. 74 """ 75 try: 76 resolve_path(val,self.search_paths) 77 except IOError, e: 78 param.Parameterized(name="%s.%s"%(obj.name,self._attrib_name)).warning('%s'%(e.args[0])) 79 80 super(Filename,self).__set__(obj,val)
81
82 - def __get__(self,obj,objtype):
83 """ 84 Return an absolute, normalized path (see resolve_path). 85 """ 86 raw_path = super(Filename,self).__get__(obj,objtype) 87 return resolve_path(raw_path,self.search_paths)
88
89 - def __getstate__(self):
90 # don't want to pickle the search_paths 91 state = super(Filename,self).__getstate__() 92 # CBALERT: uncommenting gives an error on make tests (testsnapshots.py). 93 # Testsnapshots.py runs fine on its own, and the snapshot-tests pass. 94 # Must be a test interaction? Needs investigating. 95 #del state['search_paths'] 96 return state
97 98 99 import topo 100 package_path = os.path.split(topo.__file__)[0] 101 102 # CEBALERT: we should try to remove this as soon as possible; anything 103 # relying on the location of the 'topographica' script should be 104 # re-thought (removed, or changed to output_path or package_path). 105 application_path = os.path.split(os.path.split(sys.executable)[0])[0] 106 107 # Location in which to create files; defaults to application_path. If 108 # that's not writable, uses ~/topographica (creating it if necessary). 109 if is_writable(application_path): 110 output_path = application_path 111 else: 112 home_topographica = os.path.join(os.path.expanduser("~"),'topographica') 113 if not os.path.exists(home_topographica): 114 os.mkdir(home_topographica) 115 output_path = home_topographica 116 117
118 -def resolve_path(path,search_paths=None):
119 """ 120 Find the path to an existing file, searching in the specified 121 search paths if the filename is not absolute, and converting a 122 UNIX-style path to the current OS's format if necessary. 123 124 To turn a supplied relative path into an absolute one, the path is 125 appended to each path in (search_paths+the current working 126 directory+the application's base path), in that order, until the 127 file is found. 128 129 (Similar to Python's os.path.abspath(), except more search paths 130 than just os.getcwd() can be used, and the file must exist.) 131 132 An IOError is raised if the file is not found anywhere. 133 """ 134 path = os.path.normpath(path) 135 136 if os.path.isabs(path): 137 if os.path.isfile(path): 138 return path 139 else: 140 raise IOError('File "%s" not found.'%path) 141 else: 142 all_search_paths = search_paths or [] + [os.getcwd()] + [output_path] + [package_path] + [application_path] 143 144 paths_tried = [] 145 for prefix in all_search_paths: 146 try_path = os.path.join(os.path.normpath(prefix),path) 147 if os.path.isfile(try_path): return try_path 148 paths_tried.append(try_path) 149 150 raise IOError('File "'+os.path.split(path)[1]+'" was not found in the following place(s): '+str(paths_tried)+'.')
151 152
153 -def normalize_path(path="",prefix=None):
154 """ 155 Convert a UNIX-style path to the current OS's format, 156 typically for creating a new file or directory. 157 158 If the path is not already absolute, it will be made 159 absolute (using the specified prefix, which defaults 160 to filepath.output_path) in the process. 161 162 (Should do the same as Python's os.path.abspath(), except 163 using the specified prefix rather than os.getcwd().) 164 """ 165 if not prefix: 166 prefix = output_path 167 168 if not os.path.isabs(path): 169 path = os.path.join(os.path.normpath(prefix),path) 170 171 return os.path.normpath(path)
172