1 | """ Generic file utilities for creating, parsing deleting |
---|
2 | and naming files in a manner consistent across ANUGA. |
---|
3 | """ |
---|
4 | |
---|
5 | |
---|
6 | import os, sys |
---|
7 | import csv |
---|
8 | import numpy as num |
---|
9 | import shutil |
---|
10 | import log |
---|
11 | |
---|
12 | def make_filename(s): |
---|
13 | """Transform argument string into a standard filename |
---|
14 | |
---|
15 | Convert a possible filename into a standard form. |
---|
16 | s Filename to process. |
---|
17 | The new filename string. |
---|
18 | """ |
---|
19 | |
---|
20 | s = s.strip() |
---|
21 | s = s.replace(' ', '_') |
---|
22 | s = s.replace('(', '') |
---|
23 | s = s.replace(')', '') |
---|
24 | s = s.replace('__', '_') |
---|
25 | |
---|
26 | return s |
---|
27 | |
---|
28 | |
---|
29 | def check_dir(path, verbose=None): |
---|
30 | """Check that specified path exists. |
---|
31 | If path does not exist it will be created if possible |
---|
32 | |
---|
33 | USAGE: |
---|
34 | checkdir(path, verbose): |
---|
35 | |
---|
36 | ARGUMENTS: |
---|
37 | path -- Directory |
---|
38 | verbose -- Flag verbose output (default: None) |
---|
39 | |
---|
40 | RETURN VALUE: |
---|
41 | Verified path including trailing separator |
---|
42 | """ |
---|
43 | |
---|
44 | import os.path |
---|
45 | |
---|
46 | if sys.platform in ['nt', 'dos', 'win32', 'what else?']: |
---|
47 | unix = 0 |
---|
48 | else: |
---|
49 | unix = 1 |
---|
50 | |
---|
51 | # add terminal separator, if it's not already there |
---|
52 | if path[-1] != os.sep: |
---|
53 | path = path + os.sep |
---|
54 | |
---|
55 | # expand ~ or ~username in path |
---|
56 | path = os.path.expanduser(path) |
---|
57 | |
---|
58 | # create directory if required |
---|
59 | if not (os.access(path, os.R_OK and os.W_OK) or path == ''): |
---|
60 | try: |
---|
61 | exitcode = os.mkdir(path) |
---|
62 | |
---|
63 | # Change access rights if possible |
---|
64 | if unix: |
---|
65 | exitcode = os.system('chmod 775 ' + path) |
---|
66 | else: |
---|
67 | pass # FIXME: What about access rights under Windows? |
---|
68 | |
---|
69 | if verbose: log.critical('MESSAGE: Directory %s created.' % path) |
---|
70 | except: |
---|
71 | log.critical('WARNING: Directory %s could not be created.' % path) |
---|
72 | if unix: |
---|
73 | path = '/tmp/' |
---|
74 | else: |
---|
75 | path = 'C:' + os.sep |
---|
76 | |
---|
77 | log.critical("Using directory '%s' instead" % path) |
---|
78 | |
---|
79 | return path |
---|
80 | |
---|
81 | |
---|
82 | ## |
---|
83 | # @brief Delete directory and all sub-directories. |
---|
84 | # @param path Path to the directory to delete. |
---|
85 | def del_dir(path): |
---|
86 | """Recursively delete directory path and all its contents |
---|
87 | """ |
---|
88 | |
---|
89 | if os.path.isdir(path): |
---|
90 | for file in os.listdir(path): |
---|
91 | X = os.path.join(path, file) |
---|
92 | |
---|
93 | if os.path.isdir(X) and not os.path.islink(X): |
---|
94 | del_dir(X) |
---|
95 | else: |
---|
96 | try: |
---|
97 | os.remove(X) |
---|
98 | except: |
---|
99 | log.critical("Could not remove file %s" % X) |
---|
100 | |
---|
101 | os.rmdir(path) |
---|
102 | |
---|
103 | |
---|
104 | ## |
---|
105 | # @brief ?? |
---|
106 | # @param path |
---|
107 | # @param __func__ |
---|
108 | # @param verbose True if this function is to be verbose. |
---|
109 | # @note ANOTHER OPTION, IF NEED IN THE FUTURE, Nick B 7/2007 |
---|
110 | def rmgeneric(path, func, verbose=False): |
---|
111 | ERROR_STR= """Error removing %(path)s, %(error)s """ |
---|
112 | |
---|
113 | try: |
---|
114 | func(path) |
---|
115 | if verbose: log.critical('Removed %s' % path) |
---|
116 | except OSError, (errno, strerror): |
---|
117 | log.critical(ERROR_STR % {'path' : path, 'error': strerror }) |
---|
118 | |
---|
119 | |
---|
120 | ## |
---|
121 | # @brief Remove directory and all sub-directories. |
---|
122 | # @param path Filesystem path to directory to remove. |
---|
123 | # @param verbose True if this function is to be verbose. |
---|
124 | def removeall(path, verbose=False): |
---|
125 | if not os.path.isdir(path): |
---|
126 | return |
---|
127 | |
---|
128 | for x in os.listdir(path): |
---|
129 | fullpath = os.path.join(path, x) |
---|
130 | if os.path.isfile(fullpath): |
---|
131 | f = os.remove |
---|
132 | rmgeneric(fullpath, f) |
---|
133 | elif os.path.isdir(fullpath): |
---|
134 | removeall(fullpath) |
---|
135 | f = os.rmdir |
---|
136 | rmgeneric(fullpath, f, verbose) |
---|
137 | |
---|
138 | |
---|
139 | ## |
---|
140 | # @brief Create a standard filename. |
---|
141 | # @param datadir Directory where file is to be created. |
---|
142 | # @param filename Filename 'stem'. |
---|
143 | # @param format Format of the file, becomes filename extension. |
---|
144 | # @param size Size of file, becomes part of filename. |
---|
145 | # @param time Time (float), becomes part of filename. |
---|
146 | # @return The complete filename path, including directory. |
---|
147 | # @note The containing directory is created, if necessary. |
---|
148 | def create_filename(datadir, filename, format, size=None, time=None): |
---|
149 | FN = check_dir(datadir) + filename |
---|
150 | |
---|
151 | if size is not None: |
---|
152 | FN += '_size%d' % size |
---|
153 | |
---|
154 | if time is not None: |
---|
155 | FN += '_time%.2f' % time |
---|
156 | |
---|
157 | FN += '.' + format |
---|
158 | |
---|
159 | return FN |
---|
160 | |
---|
161 | |
---|
162 | ## |
---|
163 | # @brief Get all files with a standard name and a given set of attributes. |
---|
164 | # @param datadir Directory files must be in. |
---|
165 | # @param filename Filename stem. |
---|
166 | # @param format Filename extension. |
---|
167 | # @param size Filename size. |
---|
168 | # @return A list of fielnames (including directory) that match the attributes. |
---|
169 | def get_files(datadir, filename, format, size): |
---|
170 | """Get all file (names) with given name, size and format |
---|
171 | """ |
---|
172 | |
---|
173 | import glob |
---|
174 | |
---|
175 | dir = check_dir(datadir) |
---|
176 | pattern = dir + os.sep + filename + '_size=%d*.%s' % (size, format) |
---|
177 | |
---|
178 | return glob.glob(pattern) |
---|
179 | |
---|
180 | |
---|
181 | ## |
---|
182 | # @brief Find all files in a directory that contain a given string. |
---|
183 | # @param look_in_dir Path to the directory to look in. |
---|
184 | # @param base_name String that files must contain. |
---|
185 | # @param verbose True if this function is to be verbose. |
---|
186 | def get_all_directories_with_name(look_in_dir='', base_name='', verbose=False): |
---|
187 | ''' |
---|
188 | Finds all the directories in a "look_in_dir" which contains a "base_name". |
---|
189 | |
---|
190 | Returns: a list of strings |
---|
191 | |
---|
192 | Usage: iterate_over = get_all_directories_with_name(dir, name) |
---|
193 | then: for swwfile in iterate_over: |
---|
194 | do stuff |
---|
195 | |
---|
196 | Check "export_grids" and "get_maximum_inundation_data" for examples |
---|
197 | ''' |
---|
198 | |
---|
199 | if look_in_dir == "": |
---|
200 | look_in_dir = "." # Unix compatibility |
---|
201 | |
---|
202 | dir_ls = os.listdir(look_in_dir) |
---|
203 | iterate_over = [x for x in dir_ls if base_name in x] |
---|
204 | |
---|
205 | if len(iterate_over) == 0: |
---|
206 | msg = 'No files of the base name %s' % base_name |
---|
207 | raise IOError, msg |
---|
208 | |
---|
209 | if verbose: log.critical('iterate over %s' % iterate_over) |
---|
210 | |
---|
211 | return iterate_over |
---|
212 | |
---|
213 | |
---|
214 | |
---|
215 | ## |
---|
216 | # @brief Find all SWW files in a directory with given stem name. |
---|
217 | # @param look_in_dir The directory to look in. |
---|
218 | # @param base_name The file stem name. |
---|
219 | # @param verbose True if this function is to be verbose. |
---|
220 | # @return A list of found filename strings. |
---|
221 | # @note Will accept 'base_name' with or without '.sww' extension. |
---|
222 | # @note If no files found, raises IOError exception. |
---|
223 | def get_all_swwfiles(look_in_dir='', base_name='', verbose=False): |
---|
224 | ''' |
---|
225 | Finds all the sww files in a "look_in_dir" which contains a "base_name". |
---|
226 | will accept base_name with or without the extension ".sww" |
---|
227 | |
---|
228 | Returns: a list of strings |
---|
229 | |
---|
230 | Usage: iterate_over = get_all_swwfiles(dir, name) |
---|
231 | then |
---|
232 | for swwfile in iterate_over: |
---|
233 | do stuff |
---|
234 | |
---|
235 | Check "export_grids" and "get_maximum_inundation_data" for examples |
---|
236 | ''' |
---|
237 | |
---|
238 | # plus tests the extension |
---|
239 | name, extension = os.path.splitext(base_name) |
---|
240 | |
---|
241 | if extension != '' and extension != '.sww': |
---|
242 | msg = 'file %s%s must be a NetCDF sww file!' % (base_name, extension) |
---|
243 | raise IOError, msg |
---|
244 | |
---|
245 | if look_in_dir == "": |
---|
246 | look_in_dir = "." # Unix compatibility |
---|
247 | |
---|
248 | dir_ls = os.listdir(look_in_dir) |
---|
249 | iterate_over = [x[:-4] for x in dir_ls if name in x and x[-4:] == '.sww'] |
---|
250 | if len(iterate_over) == 0: |
---|
251 | msg = 'No files of the base name %s' % name |
---|
252 | raise IOError, msg |
---|
253 | |
---|
254 | if verbose: log.critical('iterate over %s' % iterate_over) |
---|
255 | |
---|
256 | return iterate_over |
---|
257 | |
---|
258 | |
---|
259 | ## |
---|
260 | # @brief Find all files in a directory that contain a string and have extension. |
---|
261 | # @param look_in_dir Path to the directory to look in. |
---|
262 | # @param base_name Stem filename of the file(s) of interest. |
---|
263 | # @param extension Extension of the files to look for. |
---|
264 | # @param verbose True if this function is to be verbose. |
---|
265 | # @return A list of found filename strings. |
---|
266 | # @note If no files found, raises IOError exception. |
---|
267 | def get_all_files_with_extension(look_in_dir='', |
---|
268 | base_name='', |
---|
269 | extension='.sww', |
---|
270 | verbose=False): |
---|
271 | '''Find all files in a directory with given stem name. |
---|
272 | Finds all the sww files in a "look_in_dir" which contains a "base_name". |
---|
273 | |
---|
274 | Returns: a list of strings |
---|
275 | |
---|
276 | Usage: iterate_over = get_all_swwfiles(dir, name) |
---|
277 | then |
---|
278 | for swwfile in iterate_over: |
---|
279 | do stuff |
---|
280 | |
---|
281 | Check "export_grids" and "get_maximum_inundation_data" for examples |
---|
282 | ''' |
---|
283 | |
---|
284 | # plus tests the extension |
---|
285 | name, ext = os.path.splitext(base_name) |
---|
286 | |
---|
287 | if ext != '' and ext != extension: |
---|
288 | msg = 'base_name %s must be a file with %s extension!' \ |
---|
289 | % (base_name, extension) |
---|
290 | raise IOError, msg |
---|
291 | |
---|
292 | if look_in_dir == "": |
---|
293 | look_in_dir = "." # Unix compatibility |
---|
294 | |
---|
295 | dir_ls = os.listdir(look_in_dir) |
---|
296 | iterate_over = [x[:-4] for x in dir_ls if name in x and x[-4:] == extension] |
---|
297 | |
---|
298 | if len(iterate_over) == 0: |
---|
299 | msg = 'No files of the base name %s in %s' % (name, look_in_dir) |
---|
300 | raise IOError, msg |
---|
301 | |
---|
302 | if verbose: log.critical('iterate over %s' % iterate_over) |
---|
303 | |
---|
304 | return iterate_over |
---|
305 | |
---|
306 | |
---|
307 | |
---|
308 | |
---|
309 | def copy_code_files(dir_name, filename1, filename2=None, verbose=False): |
---|
310 | """Copies "filename1" and "filename2" to "dir_name". |
---|
311 | |
---|
312 | Each 'filename' may be a string or list of filename strings. |
---|
313 | |
---|
314 | Filenames must be absolute pathnames |
---|
315 | """ |
---|
316 | |
---|
317 | ## |
---|
318 | # @brief copies a file or sequence to destination directory. |
---|
319 | # @param dest The destination directory to copy to. |
---|
320 | # @param file A filename string or sequence of filename strings. |
---|
321 | def copy_file_or_sequence(dest, file): |
---|
322 | if hasattr(file, '__iter__'): |
---|
323 | for f in file: |
---|
324 | shutil.copy(f, dir_name) |
---|
325 | if verbose: |
---|
326 | log.critical('File %s copied' % f) |
---|
327 | else: |
---|
328 | shutil.copy(file, dir_name) |
---|
329 | if verbose: |
---|
330 | log.critical('File %s copied' % file) |
---|
331 | |
---|
332 | # check we have a destination directory, create if necessary |
---|
333 | if not os.path.isdir(dir_name): |
---|
334 | if verbose: |
---|
335 | log.critical('Make directory %s' % dir_name) |
---|
336 | os.mkdir(dir_name, 0777) |
---|
337 | |
---|
338 | if verbose: |
---|
339 | log.critical('Output directory: %s' % dir_name) |
---|
340 | |
---|
341 | copy_file_or_sequence(dir_name, filename1) |
---|
342 | |
---|
343 | if not filename2 is None: |
---|
344 | copy_file_or_sequence(dir_name, filename2) |
---|