source: trunk/anuga_core/source/anuga/utilities/file_utils.py @ 7876

Last change on this file since 7876 was 7841, checked in by hudson, 14 years ago

Refactorings to allow tests to pass.

File size: 10.1 KB
Line 
1""" Generic file utilities for creating, parsing deleting
2    and naming files in a manner consistent across ANUGA.
3"""
4
5
6import os, sys
7import csv
8import numpy as num
9import shutil
10import log
11
12def 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
29def 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.
85def 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
110def 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.
124def 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.
148def 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.
169def 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.
186def 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.
223def 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.
267def 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
309def 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)
Note: See TracBrowser for help on using the repository browser.